Skip to main content

zerodds_idl/ast/
types.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! AST-Typen fuer OMG IDL 4.2.
4//!
5//! Alle Typen sind owned (`String`, `Vec`, `Box`) — kein Source-Borrowing.
6//! Damit kann der AST den Source-String ueberleben und z.B. in Build-
7//! Pipelines weitergereicht werden, in denen die Quelldatei bereits
8//! geschlossen ist.
9//!
10//! # Span-Konvention
11//! Jeder Node, der Diagnostik-relevant ist, traegt ein `span: Span` —
12//! Byte-Offset im Source-Text. Hilfs-Strukturen ohne unabhaengige
13//! Diagnostik (z.B. [`PrimitiveType`]) sind ohne Span.
14
15#![allow(missing_docs)] // Doc-Kommentare folgen mit T5.7
16
17use crate::errors::Span;
18
19// ============================================================================
20// Spezifikation / Definition
21// ============================================================================
22
23/// Wurzelknoten — entspricht `<specification>` (§7.4.1.1).
24#[derive(Debug, Clone, PartialEq)]
25pub struct Specification {
26    pub definitions: Vec<Definition>,
27    pub span: Span,
28}
29
30/// Top-Level-Definition. Entspricht `<definition>` (§7.4.1.2) plus
31/// optionalem `VendorExtension`-Catch-All fuer Delta-eingefuegte
32/// Konstrukte (T6.5).
33#[derive(Debug, Clone, PartialEq)]
34pub enum Definition {
35    Module(ModuleDef),
36    Type(TypeDecl),
37    Const(ConstDecl),
38    Except(ExceptDecl),
39    Interface(InterfaceDcl),
40    ValueBox(ValueBoxDecl),
41    ValueForward(ValueForwardDecl),
42    /// `valuetype <name> [: <inheritance>] [supports <ifaces>] { <elements> };`
43    /// (§7.4.5.4 Rule 99).
44    ValueDef(ValueDef),
45    /// `typeid <scoped_name> "<repo-id>";` (§7.4.6.3 Rule 113).
46    TypeId(TypeIdDcl),
47    /// `typeprefix <scoped_name> "<prefix>";` (§7.4.6.3 Rule 114).
48    TypePrefix(TypePrefixDcl),
49    /// `import <imported_scope>;` (§7.4.6.3 Rule 115).
50    Import(ImportDcl),
51    /// `component <name> [: base] [supports …] { … };` (§7.4.8.3 Rule 134).
52    Component(ComponentDcl),
53    /// `home <name> [: base] [supports …] manages <comp> [primarykey K] { … };`
54    /// (§7.4.9.3 Rule 145).
55    Home(HomeDcl),
56    /// `eventtype <name> { … };` / `abstract eventtype` / `eventtype X;`
57    /// (§7.4.10.3 Rule 166).
58    Event(EventDcl),
59    /// `porttype <name> { … };` / `porttype X;` (§7.4.11.3 Rule 172).
60    Porttype(PorttypeDcl),
61    /// `connector <name> [: base] { <port_ref>+ };` (§7.4.11.3 Rule 180).
62    Connector(ConnectorDcl),
63    /// `module <name> < <formal_params> > { <tpl_definition>+ };`
64    /// (§7.4.12.3 Rule 185).
65    TemplateModule(TemplateModuleDcl),
66    /// `module <scoped_name>< <actual_params> > <new_name>;`
67    /// (§7.4.12.3 Rule 190).
68    TemplateModuleInst(TemplateModuleInst),
69    /// User-Defined `@annotation Foo { ... };` (§7.4.15 Rules 218-221).
70    Annotation(AnnotationDcl),
71    /// Top-Level-Konstrukt aus einer Vendor-Delta-Erweiterung
72    /// (z.B. `keylist Type (fields);` aus dem RTI-Delta). Span deckt
73    /// das gesamte Konstrukt ab; `production_name` ist der Production-
74    /// Name aus der Delta-Definition.
75    VendorExtension(VendorExtension),
76}
77
78impl Definition {
79    /// Gemeinsamer Span-Accessor.
80    #[must_use]
81    pub fn span(&self) -> Span {
82        match self {
83            Self::Module(d) => d.span,
84            Self::Type(d) => d.span(),
85            Self::Const(d) => d.span,
86            Self::Except(d) => d.span,
87            Self::Interface(d) => d.span(),
88            Self::ValueBox(d) => d.span,
89            Self::ValueForward(d) => d.span,
90            Self::ValueDef(d) => d.span,
91            Self::TypeId(d) => d.span,
92            Self::TypePrefix(d) => d.span,
93            Self::Import(d) => d.span,
94            Self::Component(d) => d.span(),
95            Self::Home(d) => d.span(),
96            Self::Event(d) => d.span(),
97            Self::Porttype(d) => d.span(),
98            Self::Connector(d) => d.span,
99            Self::TemplateModule(d) => d.span,
100            Self::TemplateModuleInst(d) => d.span,
101            Self::Annotation(d) => d.span,
102            Self::VendorExtension(v) => v.span,
103        }
104    }
105}
106
107/// User-Defined Annotation Declaration (§7.4.15).
108///
109/// `@annotation <name> { <member>* };` mit Members gem Rule 220:
110/// `annotation_member` (CONST_TYPE simple_declarator [default expr])
111/// oder embedded `enum_dcl`/`const_dcl`/`typedef_dcl`.
112#[derive(Debug, Clone, PartialEq)]
113pub struct AnnotationDcl {
114    pub name: Identifier,
115    pub members: Vec<AnnotationMember>,
116    pub embedded_types: Vec<TypeDecl>,
117    pub embedded_consts: Vec<ConstDecl>,
118    pub span: Span,
119}
120
121/// Member-Slot (§7.4.15 Rule 221).
122#[derive(Debug, Clone, PartialEq)]
123pub struct AnnotationMember {
124    pub name: Identifier,
125    pub type_spec: ConstType,
126    pub default: Option<ConstExpr>,
127    pub span: Span,
128}
129
130// ============================================================================
131// CORBA-Specific Top-Level-Decls (§7.4.6.3)
132// ============================================================================
133
134/// `typeid <scoped_name> "<repo-id>";` (§7.4.6.3 Rule 113).
135#[derive(Debug, Clone, PartialEq)]
136pub struct TypeIdDcl {
137    pub target: ScopedName,
138    pub repository_id: String,
139    pub span: Span,
140}
141
142/// `typeprefix <scoped_name> "<prefix>";` (§7.4.6.3 Rule 114).
143#[derive(Debug, Clone, PartialEq)]
144pub struct TypePrefixDcl {
145    pub target: ScopedName,
146    pub prefix: String,
147    pub span: Span,
148}
149
150/// `import <imported_scope>;` (§7.4.6.3 Rule 115).
151#[derive(Debug, Clone, PartialEq)]
152pub struct ImportDcl {
153    pub imported: ImportedScope,
154    pub span: Span,
155}
156
157/// `<imported_scope>` — Scoped-Name oder String-Repository-ID.
158#[derive(Debug, Clone, PartialEq)]
159pub enum ImportedScope {
160    Scoped(ScopedName),
161    Repository(String),
162}
163
164// ============================================================================
165// Value-Type Full Definition (§7.4.5.4)
166// ============================================================================
167
168/// `valuetype <name> [: <inheritance>] [supports <ifaces>] { <elements> };`
169/// (§7.4.5.4 Rule 99 + §7.4.7.3 Custom/Abstract-Variants).
170#[derive(Debug, Clone, PartialEq)]
171pub struct ValueDef {
172    pub name: Identifier,
173    pub kind: ValueKind,
174    pub inheritance: Option<ValueInheritanceSpec>,
175    pub elements: Vec<ValueElement>,
176    pub annotations: Vec<Annotation>,
177    pub span: Span,
178}
179
180#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181pub enum ValueKind {
182    /// `valuetype <name> { … };`.
183    Concrete,
184    /// `custom valuetype <name> { … };` (§7.4.7.3 Rule 128).
185    Custom,
186    /// `abstract valuetype <name> { … };` (§7.4.7.3 Rule 127).
187    Abstract,
188}
189
190/// `: [truncatable] <value_name>{,…} [supports <iface>{,…}]` (Rules 102-104,130).
191#[derive(Debug, Clone, PartialEq)]
192pub struct ValueInheritanceSpec {
193    pub truncatable: bool,
194    pub bases: Vec<ScopedName>,
195    pub supports: Vec<ScopedName>,
196    pub span: Span,
197}
198
199/// `<value_element>` (§7.4.5.4.1.3 Rule 105).
200#[derive(Debug, Clone, PartialEq)]
201pub enum ValueElement {
202    /// `<export>` — Op/Attr/Type/Const/Except (analog Interface-Body).
203    Export(Export),
204    /// `<state_member>` mit Visibility (Rule 106).
205    State(StateMember),
206    /// `<init_dcl>` — `factory <name>(<params>) [<raises>];` (Rule 107).
207    Init(InitDcl),
208}
209
210#[derive(Debug, Clone, PartialEq)]
211pub struct StateMember {
212    pub visibility: StateVisibility,
213    pub type_spec: TypeSpec,
214    pub declarators: Vec<Declarator>,
215    pub annotations: Vec<Annotation>,
216    pub span: Span,
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq)]
220pub enum StateVisibility {
221    Public,
222    Private,
223}
224
225#[derive(Debug, Clone, PartialEq)]
226pub struct InitDcl {
227    pub name: Identifier,
228    pub params: Vec<ParamDecl>,
229    pub raises: Vec<ScopedName>,
230    pub span: Span,
231}
232
233// ============================================================================
234// Components – Basic + Homes + CCM-Specific (§7.4.8 - §7.4.10)
235// ============================================================================
236
237#[derive(Debug, Clone, PartialEq)]
238pub enum ComponentDcl {
239    Def(ComponentDef),
240    Forward(Identifier, Span),
241}
242
243impl ComponentDcl {
244    #[must_use]
245    pub fn span(&self) -> Span {
246        match self {
247            Self::Def(d) => d.span,
248            Self::Forward(_, s) => *s,
249        }
250    }
251}
252
253#[derive(Debug, Clone, PartialEq)]
254pub struct ComponentDef {
255    pub name: Identifier,
256    pub base: Option<ScopedName>,
257    pub supports: Vec<ScopedName>,
258    pub body: Vec<ComponentExport>,
259    pub annotations: Vec<Annotation>,
260    pub span: Span,
261}
262
263#[derive(Debug, Clone, PartialEq)]
264pub enum ComponentExport {
265    Provides {
266        type_spec: ScopedName,
267        name: Identifier,
268        span: Span,
269    },
270    Uses {
271        type_spec: ScopedName,
272        name: Identifier,
273        multiple: bool,
274        span: Span,
275    },
276    Attribute(AttrDcl),
277    /// `emits <T> <name>;` (§7.4.10.3 Rule 159).
278    Emits {
279        type_spec: ScopedName,
280        name: Identifier,
281        span: Span,
282    },
283    /// `publishes <T> <name>;` (Rule 160).
284    Publishes {
285        type_spec: ScopedName,
286        name: Identifier,
287        span: Span,
288    },
289    /// `consumes <T> <name>;` (Rule 161).
290    Consumes {
291        type_spec: ScopedName,
292        name: Identifier,
293        span: Span,
294    },
295    /// `port <T> <name>;` / `mirrorport <T> <name>;` (§7.4.11.3 Rule 178).
296    Port {
297        type_spec: ScopedName,
298        name: Identifier,
299        mirror: bool,
300        span: Span,
301    },
302}
303
304/// Attribut-Decl-Stub fuer Components/Homes/Values (vereinfachte Form;
305/// volle Attr-Decl ist in der Interface-Pipeline).
306#[derive(Debug, Clone, PartialEq)]
307pub struct AttrDcl {
308    pub readonly: bool,
309    pub type_spec: TypeSpec,
310    pub name: Identifier,
311    pub span: Span,
312}
313
314#[derive(Debug, Clone, PartialEq)]
315pub enum HomeDcl {
316    Def(HomeDef),
317    Forward(Identifier, Span),
318}
319
320impl HomeDcl {
321    #[must_use]
322    pub fn span(&self) -> Span {
323        match self {
324            Self::Def(d) => d.span,
325            Self::Forward(_, s) => *s,
326        }
327    }
328}
329
330#[derive(Debug, Clone, PartialEq)]
331pub struct HomeDef {
332    pub name: Identifier,
333    pub base: Option<ScopedName>,
334    pub supports: Vec<ScopedName>,
335    pub manages: ScopedName,
336    pub primary_key: Option<ScopedName>,
337    pub annotations: Vec<Annotation>,
338    pub span: Span,
339}
340
341#[derive(Debug, Clone, PartialEq)]
342pub enum EventDcl {
343    Def(EventDef),
344    Forward(Identifier, Span),
345}
346
347impl EventDcl {
348    #[must_use]
349    pub fn span(&self) -> Span {
350        match self {
351            Self::Def(d) => d.span,
352            Self::Forward(_, s) => *s,
353        }
354    }
355}
356
357#[derive(Debug, Clone, PartialEq)]
358pub struct EventDef {
359    pub name: Identifier,
360    pub kind: ValueKind,
361    pub inheritance: Option<ValueInheritanceSpec>,
362    pub elements: Vec<ValueElement>,
363    pub annotations: Vec<Annotation>,
364    pub span: Span,
365}
366
367// ============================================================================
368// Ports + Connectors (§7.4.11)
369// ============================================================================
370
371#[derive(Debug, Clone, PartialEq)]
372pub enum PorttypeDcl {
373    Def(PorttypeDef),
374    Forward(Identifier, Span),
375}
376
377impl PorttypeDcl {
378    #[must_use]
379    pub fn span(&self) -> Span {
380        match self {
381            Self::Def(d) => d.span,
382            Self::Forward(_, s) => *s,
383        }
384    }
385}
386
387#[derive(Debug, Clone, PartialEq)]
388pub struct PorttypeDef {
389    pub name: Identifier,
390    pub body: Vec<ComponentExport>,
391    pub span: Span,
392}
393
394#[derive(Debug, Clone, PartialEq)]
395pub struct ConnectorDcl {
396    pub name: Identifier,
397    pub base: Option<ScopedName>,
398    pub body: Vec<ComponentExport>,
399    pub span: Span,
400}
401
402// ============================================================================
403// Template Modules (§7.4.12)
404// ============================================================================
405
406#[derive(Debug, Clone, PartialEq)]
407pub struct TemplateModuleDcl {
408    pub name: Identifier,
409    pub formal_params: Vec<FormalParam>,
410    pub definitions: Vec<Definition>,
411    pub span: Span,
412}
413
414#[derive(Debug, Clone, PartialEq)]
415pub struct FormalParam {
416    pub kind: FormalParamKind,
417    pub name: Identifier,
418    pub span: Span,
419}
420
421#[derive(Debug, Clone, PartialEq)]
422pub enum FormalParamKind {
423    Typename,
424    Interface,
425    Valuetype,
426    Eventtype,
427    Struct,
428    Union,
429    Exception,
430    Enum,
431    Sequence,
432    Const(ConstType),
433    SequenceType(SequenceType),
434}
435
436#[derive(Debug, Clone, PartialEq)]
437pub struct TemplateModuleInst {
438    pub template: ScopedName,
439    pub actual_params: Vec<ConstExpr>,
440    pub instance_name: Identifier,
441    pub span: Span,
442}
443
444/// Catch-All fuer Vendor-Delta-eingefuegte Top-Level-Konstrukte.
445/// AST-Builder lässt die innere Struktur unausgewertet — der
446/// AST-Builder pro Vendor-Delta soll das in einer spaeteren Phase
447/// reichern.
448#[derive(Debug, Clone, PartialEq)]
449pub struct VendorExtension {
450    /// Production-Name aus der Delta-Definition (z.B. `"rti_keylist"`).
451    pub production_name: String,
452    /// Roher Source-Slice der Konstruktion fuer Diagnostik.
453    pub raw: String,
454    pub span: Span,
455}
456
457/// `module <ident> { <definition>* };`.
458#[derive(Debug, Clone, PartialEq)]
459pub struct ModuleDef {
460    pub name: Identifier,
461    pub definitions: Vec<Definition>,
462    pub annotations: Vec<Annotation>,
463    pub span: Span,
464}
465
466// ============================================================================
467// Type-Decl
468// ============================================================================
469
470#[derive(Debug, Clone, PartialEq)]
471pub enum TypeDecl {
472    Constr(ConstrTypeDecl),
473    Typedef(TypedefDecl),
474}
475
476impl TypeDecl {
477    #[must_use]
478    pub fn span(&self) -> Span {
479        match self {
480            Self::Constr(d) => d.span(),
481            Self::Typedef(d) => d.span,
482        }
483    }
484}
485
486#[derive(Debug, Clone, PartialEq)]
487pub enum ConstrTypeDecl {
488    Struct(StructDcl),
489    Union(UnionDcl),
490    Enum(EnumDef),
491    Bitset(BitsetDecl),
492    Bitmask(BitmaskDecl),
493}
494
495impl ConstrTypeDecl {
496    #[must_use]
497    pub fn span(&self) -> Span {
498        match self {
499            Self::Struct(d) => d.span(),
500            Self::Union(d) => d.span(),
501            Self::Enum(d) => d.span,
502            Self::Bitset(d) => d.span,
503            Self::Bitmask(d) => d.span,
504        }
505    }
506}
507
508// ============================================================================
509// Struct
510// ============================================================================
511
512#[derive(Debug, Clone, PartialEq)]
513pub enum StructDcl {
514    Def(StructDef),
515    Forward(StructForwardDecl),
516}
517
518impl StructDcl {
519    #[must_use]
520    pub fn span(&self) -> Span {
521        match self {
522            Self::Def(d) => d.span,
523            Self::Forward(d) => d.span,
524        }
525    }
526}
527
528#[derive(Debug, Clone, PartialEq)]
529pub struct StructDef {
530    pub name: Identifier,
531    /// Optionaler Basis-Typ (Extended Data Types BB §7.4.13).
532    pub base: Option<ScopedName>,
533    pub members: Vec<Member>,
534    pub annotations: Vec<Annotation>,
535    pub span: Span,
536}
537
538#[derive(Debug, Clone, PartialEq)]
539pub struct StructForwardDecl {
540    pub name: Identifier,
541    pub span: Span,
542}
543
544#[derive(Debug, Clone, PartialEq)]
545pub struct Member {
546    pub type_spec: TypeSpec,
547    pub declarators: Vec<Declarator>,
548    pub annotations: Vec<Annotation>,
549    pub span: Span,
550}
551
552// ============================================================================
553// Union
554// ============================================================================
555
556#[derive(Debug, Clone, PartialEq)]
557pub enum UnionDcl {
558    Def(UnionDef),
559    Forward(UnionForwardDecl),
560}
561
562impl UnionDcl {
563    #[must_use]
564    pub fn span(&self) -> Span {
565        match self {
566            Self::Def(d) => d.span,
567            Self::Forward(d) => d.span,
568        }
569    }
570}
571
572#[derive(Debug, Clone, PartialEq)]
573pub struct UnionDef {
574    pub name: Identifier,
575    pub switch_type: SwitchTypeSpec,
576    pub cases: Vec<Case>,
577    pub annotations: Vec<Annotation>,
578    pub span: Span,
579}
580
581#[derive(Debug, Clone, PartialEq)]
582pub struct UnionForwardDecl {
583    pub name: Identifier,
584    pub span: Span,
585}
586
587#[derive(Debug, Clone, PartialEq)]
588pub enum SwitchTypeSpec {
589    Integer(IntegerType),
590    Char,
591    Boolean,
592    Octet,
593    Scoped(ScopedName),
594}
595
596#[derive(Debug, Clone, PartialEq)]
597pub struct Case {
598    pub labels: Vec<CaseLabel>,
599    pub element: ElementSpec,
600    pub annotations: Vec<Annotation>,
601    pub span: Span,
602}
603
604#[derive(Debug, Clone, PartialEq)]
605pub enum CaseLabel {
606    /// `case <expr>:`.
607    Value(ConstExpr),
608    /// `default:`.
609    Default,
610}
611
612#[derive(Debug, Clone, PartialEq)]
613pub struct ElementSpec {
614    pub type_spec: TypeSpec,
615    pub declarator: Declarator,
616    pub annotations: Vec<Annotation>,
617    pub span: Span,
618}
619
620// ============================================================================
621// Enum
622// ============================================================================
623
624#[derive(Debug, Clone, PartialEq)]
625pub struct EnumDef {
626    pub name: Identifier,
627    pub enumerators: Vec<Enumerator>,
628    pub annotations: Vec<Annotation>,
629    pub span: Span,
630}
631
632#[derive(Debug, Clone, PartialEq)]
633pub struct Enumerator {
634    pub name: Identifier,
635    pub annotations: Vec<Annotation>,
636    pub span: Span,
637}
638
639// ============================================================================
640// Bitset / Bitmask
641// ============================================================================
642
643#[derive(Debug, Clone, PartialEq)]
644pub struct BitsetDecl {
645    pub name: Identifier,
646    pub base: Option<ScopedName>,
647    pub bitfields: Vec<Bitfield>,
648    pub annotations: Vec<Annotation>,
649    pub span: Span,
650}
651
652#[derive(Debug, Clone, PartialEq)]
653pub struct Bitfield {
654    pub spec: BitfieldSpec,
655    /// `None` bei anonymen Padding-Bitfields.
656    pub name: Option<Identifier>,
657    pub annotations: Vec<Annotation>,
658    pub span: Span,
659}
660
661#[derive(Debug, Clone, PartialEq)]
662pub struct BitfieldSpec {
663    pub width: ConstExpr,
664    pub dest_type: Option<PrimitiveType>,
665    pub span: Span,
666}
667
668#[derive(Debug, Clone, PartialEq)]
669pub struct BitmaskDecl {
670    pub name: Identifier,
671    pub values: Vec<BitValue>,
672    pub annotations: Vec<Annotation>,
673    pub span: Span,
674}
675
676#[derive(Debug, Clone, PartialEq)]
677pub struct BitValue {
678    pub name: Identifier,
679    pub annotations: Vec<Annotation>,
680    pub span: Span,
681}
682
683// ============================================================================
684// Typedef + Declarators
685// ============================================================================
686
687#[derive(Debug, Clone, PartialEq)]
688pub struct TypedefDecl {
689    pub type_spec: TypeSpec,
690    pub declarators: Vec<Declarator>,
691    pub annotations: Vec<Annotation>,
692    pub span: Span,
693}
694
695#[derive(Debug, Clone, PartialEq)]
696pub enum Declarator {
697    Simple(Identifier),
698    Array(ArrayDeclarator),
699}
700
701impl Declarator {
702    #[must_use]
703    pub fn name(&self) -> &Identifier {
704        match self {
705            Self::Simple(n) => n,
706            Self::Array(a) => &a.name,
707        }
708    }
709
710    #[must_use]
711    pub fn span(&self) -> Span {
712        match self {
713            Self::Simple(n) => n.span,
714            Self::Array(a) => a.span,
715        }
716    }
717}
718
719#[derive(Debug, Clone, PartialEq)]
720pub struct ArrayDeclarator {
721    pub name: Identifier,
722    pub sizes: Vec<ConstExpr>,
723    pub span: Span,
724}
725
726// ============================================================================
727// Const Decl + ConstExpr
728// ============================================================================
729
730#[derive(Debug, Clone, PartialEq)]
731pub struct ConstDecl {
732    pub name: Identifier,
733    pub type_: ConstType,
734    pub value: ConstExpr,
735    pub annotations: Vec<Annotation>,
736    pub span: Span,
737}
738
739/// Eingeschraenkter Type-Spec fuer `const`-Decls (§7.4.1.4.4.5).
740#[derive(Debug, Clone, PartialEq)]
741pub enum ConstType {
742    Integer(IntegerType),
743    Floating(FloatingType),
744    Char,
745    WideChar,
746    Boolean,
747    Octet,
748    String { wide: bool },
749    Fixed,
750    Scoped(ScopedName),
751}
752
753/// Ausdruck — entspricht `<const_expr>` und Sub-Productions.
754#[derive(Debug, Clone, PartialEq)]
755pub enum ConstExpr {
756    Literal(Literal),
757    Scoped(ScopedName),
758    Unary {
759        op: UnaryOp,
760        operand: Box<ConstExpr>,
761        span: Span,
762    },
763    Binary {
764        op: BinaryOp,
765        lhs: Box<ConstExpr>,
766        rhs: Box<ConstExpr>,
767        span: Span,
768    },
769}
770
771impl ConstExpr {
772    #[must_use]
773    pub fn span(&self) -> Span {
774        match self {
775            Self::Literal(l) => l.span,
776            Self::Scoped(s) => s.span,
777            Self::Unary { span, .. } | Self::Binary { span, .. } => *span,
778        }
779    }
780}
781
782#[derive(Debug, Clone, Copy, PartialEq, Eq)]
783pub enum UnaryOp {
784    Plus,
785    Minus,
786    BitNot,
787}
788
789#[derive(Debug, Clone, Copy, PartialEq, Eq)]
790pub enum BinaryOp {
791    Or,
792    Xor,
793    And,
794    Shl,
795    Shr,
796    Add,
797    Sub,
798    Mul,
799    Div,
800    Mod,
801}
802
803/// Literal-Wert — Inhalt aus dem Source-Text uebernommen.
804#[derive(Debug, Clone, PartialEq)]
805pub struct Literal {
806    pub kind: LiteralKind,
807    /// Roh-Text aus dem Source (inkl. Quotes/Suffix). Semantische
808    /// Konvertierung passiert erst im AST-Builder/Validator.
809    pub raw: String,
810    pub span: Span,
811}
812
813#[derive(Debug, Clone, Copy, PartialEq, Eq)]
814pub enum LiteralKind {
815    Integer,
816    Floating,
817    Fixed,
818    Char,
819    WideChar,
820    String,
821    WideString,
822    Boolean,
823}
824
825// ============================================================================
826// Exception
827// ============================================================================
828
829#[derive(Debug, Clone, PartialEq)]
830pub struct ExceptDecl {
831    pub name: Identifier,
832    pub members: Vec<Member>,
833    pub annotations: Vec<Annotation>,
834    pub span: Span,
835}
836
837// ============================================================================
838// Interface
839// ============================================================================
840
841#[derive(Debug, Clone, PartialEq)]
842pub enum InterfaceDcl {
843    Def(InterfaceDef),
844    Forward(InterfaceForwardDecl),
845}
846
847impl InterfaceDcl {
848    #[must_use]
849    pub fn span(&self) -> Span {
850        match self {
851            Self::Def(d) => d.span,
852            Self::Forward(d) => d.span,
853        }
854    }
855}
856
857#[derive(Debug, Clone, PartialEq)]
858pub struct InterfaceDef {
859    pub kind: InterfaceKind,
860    pub name: Identifier,
861    pub bases: Vec<ScopedName>,
862    pub exports: Vec<Export>,
863    pub annotations: Vec<Annotation>,
864    pub span: Span,
865}
866
867#[derive(Debug, Clone, PartialEq)]
868pub struct InterfaceForwardDecl {
869    pub kind: InterfaceKind,
870    pub name: Identifier,
871    pub span: Span,
872}
873
874#[derive(Debug, Clone, Copy, PartialEq, Eq)]
875pub enum InterfaceKind {
876    Plain,
877    Abstract,
878    Local,
879}
880
881#[derive(Debug, Clone, PartialEq)]
882pub enum Export {
883    Op(OpDecl),
884    Attr(AttrDecl),
885    Type(TypeDecl),
886    Const(ConstDecl),
887    Except(ExceptDecl),
888}
889
890impl Export {
891    #[must_use]
892    pub fn span(&self) -> Span {
893        match self {
894            Self::Op(d) => d.span,
895            Self::Attr(d) => d.span,
896            Self::Type(d) => d.span(),
897            Self::Const(d) => d.span,
898            Self::Except(d) => d.span,
899        }
900    }
901}
902
903#[derive(Debug, Clone, PartialEq)]
904pub struct OpDecl {
905    pub name: Identifier,
906    pub oneway: bool,
907    /// `None` bei `void`, `Some` sonst.
908    pub return_type: Option<TypeSpec>,
909    pub params: Vec<ParamDecl>,
910    pub raises: Vec<ScopedName>,
911    pub annotations: Vec<Annotation>,
912    pub span: Span,
913}
914
915#[derive(Debug, Clone, PartialEq)]
916pub struct ParamDecl {
917    pub attribute: ParamAttribute,
918    pub type_spec: TypeSpec,
919    pub name: Identifier,
920    pub annotations: Vec<Annotation>,
921    pub span: Span,
922}
923
924#[derive(Debug, Clone, Copy, PartialEq, Eq)]
925pub enum ParamAttribute {
926    In,
927    Out,
928    InOut,
929}
930
931#[derive(Debug, Clone, PartialEq)]
932pub struct AttrDecl {
933    pub name: Identifier,
934    pub type_spec: TypeSpec,
935    pub readonly: bool,
936    /// `getraises` / readonly `raises` Liste (§7.4.3.1 Rules 91/95).
937    /// Bei readonly-Attribute ist das die `raises_expr`-Liste; bei
938    /// writable-Attribute die `getraises`-Liste.
939    pub get_raises: Vec<ScopedName>,
940    /// `setraises` Liste (§7.4.3.1 Rule 96). Nur bei writable-Attribute
941    /// nicht-leer.
942    pub set_raises: Vec<ScopedName>,
943    pub annotations: Vec<Annotation>,
944    pub span: Span,
945}
946
947// ============================================================================
948// Valuetype (minimal — siehe T-LIM-5)
949// ============================================================================
950
951#[derive(Debug, Clone, PartialEq)]
952pub struct ValueBoxDecl {
953    pub name: Identifier,
954    pub type_spec: TypeSpec,
955    pub annotations: Vec<Annotation>,
956    pub span: Span,
957}
958
959#[derive(Debug, Clone, PartialEq)]
960pub struct ValueForwardDecl {
961    pub name: Identifier,
962    pub span: Span,
963}
964
965// ============================================================================
966// Type-Spec
967// ============================================================================
968
969#[derive(Debug, Clone, PartialEq)]
970pub enum TypeSpec {
971    Primitive(PrimitiveType),
972    Scoped(ScopedName),
973    Sequence(SequenceType),
974    String(StringType),
975    Fixed(FixedPtType),
976    Map(MapType),
977    Any,
978}
979
980#[derive(Debug, Clone, Copy, PartialEq, Eq)]
981pub enum PrimitiveType {
982    Integer(IntegerType),
983    Floating(FloatingType),
984    Char,
985    WideChar,
986    Boolean,
987    Octet,
988}
989
990#[derive(Debug, Clone, Copy, PartialEq, Eq)]
991pub enum IntegerType {
992    Short,
993    Long,
994    LongLong,
995    UShort,
996    ULong,
997    ULongLong,
998    Int8,
999    Int16,
1000    Int32,
1001    Int64,
1002    UInt8,
1003    UInt16,
1004    UInt32,
1005    UInt64,
1006}
1007
1008#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1009pub enum FloatingType {
1010    Float,
1011    Double,
1012    LongDouble,
1013}
1014
1015#[derive(Debug, Clone, PartialEq)]
1016pub struct SequenceType {
1017    pub elem: Box<TypeSpec>,
1018    /// `None` = unbounded.
1019    pub bound: Option<ConstExpr>,
1020    pub span: Span,
1021}
1022
1023#[derive(Debug, Clone, PartialEq)]
1024pub struct StringType {
1025    pub wide: bool,
1026    pub bound: Option<ConstExpr>,
1027    pub span: Span,
1028}
1029
1030#[derive(Debug, Clone, PartialEq)]
1031pub struct FixedPtType {
1032    pub digits: ConstExpr,
1033    pub scale: ConstExpr,
1034    pub span: Span,
1035}
1036
1037#[derive(Debug, Clone, PartialEq)]
1038pub struct MapType {
1039    pub key: Box<TypeSpec>,
1040    pub value: Box<TypeSpec>,
1041    pub bound: Option<ConstExpr>,
1042    pub span: Span,
1043}
1044
1045// ============================================================================
1046// Annotations
1047// ============================================================================
1048
1049#[derive(Debug, Clone, PartialEq)]
1050pub struct Annotation {
1051    pub name: ScopedName,
1052    pub params: AnnotationParams,
1053    pub span: Span,
1054}
1055
1056#[derive(Debug, Clone, PartialEq)]
1057pub enum AnnotationParams {
1058    /// `@key` — kein Klammerpaar.
1059    None,
1060    /// `@id()` — leeres Klammerpaar.
1061    Empty,
1062    /// `@id(7)` — einzelner positionaler Ausdruck.
1063    Single(ConstExpr),
1064    /// `@range(min=0, max=10)` — Liste benannter Parameter.
1065    Named(Vec<NamedParam>),
1066}
1067
1068#[derive(Debug, Clone, PartialEq)]
1069pub struct NamedParam {
1070    pub name: Identifier,
1071    pub value: ConstExpr,
1072    pub span: Span,
1073}
1074
1075// ============================================================================
1076// Identifier / ScopedName
1077// ============================================================================
1078
1079/// Einfacher Identifier mit Span.
1080#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1081pub struct Identifier {
1082    pub text: String,
1083    pub span: Span,
1084}
1085
1086impl Identifier {
1087    #[must_use]
1088    pub fn new(text: impl Into<String>, span: Span) -> Self {
1089        Self {
1090            text: text.into(),
1091            span,
1092        }
1093    }
1094}
1095
1096/// Scoped-Name `[::] <ident> ( :: <ident> )*` (§7.4.1.4.2).
1097#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1098pub struct ScopedName {
1099    /// `true`, wenn der Name mit `::` beginnt (absolute Pfad).
1100    pub absolute: bool,
1101    pub parts: Vec<Identifier>,
1102    pub span: Span,
1103}
1104
1105impl ScopedName {
1106    #[must_use]
1107    pub fn single(ident: Identifier) -> Self {
1108        let span = ident.span;
1109        Self {
1110            absolute: false,
1111            parts: vec![ident],
1112            span,
1113        }
1114    }
1115}
1116
1117#[cfg(test)]
1118mod tests {
1119    #![allow(clippy::expect_used)]
1120    use super::*;
1121
1122    fn s(start: usize, end: usize) -> Span {
1123        Span::new(start, end)
1124    }
1125
1126    #[test]
1127    fn identifier_new_stores_text_and_span() {
1128        let id = Identifier::new("Foo", s(0, 3));
1129        assert_eq!(id.text, "Foo");
1130        assert_eq!(id.span, s(0, 3));
1131    }
1132
1133    #[test]
1134    fn scoped_name_single_wraps_identifier() {
1135        let id = Identifier::new("Foo", s(0, 3));
1136        let sn = ScopedName::single(id.clone());
1137        assert!(!sn.absolute);
1138        assert_eq!(sn.parts, vec![id]);
1139        assert_eq!(sn.span, s(0, 3));
1140    }
1141
1142    #[test]
1143    fn definition_span_dispatches_per_variant() {
1144        let m = Definition::Module(ModuleDef {
1145            name: Identifier::new("M", s(7, 8)),
1146            definitions: vec![],
1147            annotations: vec![],
1148            span: s(0, 20),
1149        });
1150        assert_eq!(m.span(), s(0, 20));
1151    }
1152
1153    #[test]
1154    fn const_expr_span_dispatches_per_variant() {
1155        let lit = ConstExpr::Literal(Literal {
1156            kind: LiteralKind::Integer,
1157            raw: "42".to_string(),
1158            span: s(0, 2),
1159        });
1160        assert_eq!(lit.span(), s(0, 2));
1161        let unary = ConstExpr::Unary {
1162            op: UnaryOp::Minus,
1163            operand: Box::new(lit.clone()),
1164            span: s(0, 3),
1165        };
1166        assert_eq!(unary.span(), s(0, 3));
1167    }
1168
1169    #[test]
1170    fn declarator_name_returns_identifier() {
1171        let id = Identifier::new("buf", s(0, 3));
1172        let d = Declarator::Simple(id.clone());
1173        assert_eq!(d.name(), &id);
1174        assert_eq!(d.span(), s(0, 3));
1175
1176        let arr = Declarator::Array(ArrayDeclarator {
1177            name: Identifier::new("matrix", s(5, 11)),
1178            sizes: vec![],
1179            span: s(5, 15),
1180        });
1181        assert_eq!(arr.name().text, "matrix");
1182        assert_eq!(arr.span(), s(5, 15));
1183    }
1184
1185    #[test]
1186    fn export_span_dispatches_per_variant() {
1187        let op = Export::Op(OpDecl {
1188            name: Identifier::new("ping", s(0, 4)),
1189            oneway: false,
1190            return_type: None,
1191            params: vec![],
1192            raises: vec![],
1193            annotations: vec![],
1194            span: s(0, 10),
1195        });
1196        assert_eq!(op.span(), s(0, 10));
1197    }
1198
1199    #[test]
1200    fn type_decl_span_dispatches() {
1201        let td = TypeDecl::Typedef(TypedefDecl {
1202            type_spec: TypeSpec::Primitive(PrimitiveType::Boolean),
1203            declarators: vec![],
1204            annotations: vec![],
1205            span: s(2, 10),
1206        });
1207        assert_eq!(td.span(), s(2, 10));
1208    }
1209
1210    #[test]
1211    fn struct_dcl_span_dispatches() {
1212        let sd = StructDcl::Forward(StructForwardDecl {
1213            name: Identifier::new("Foo", s(7, 10)),
1214            span: s(0, 11),
1215        });
1216        assert_eq!(sd.span(), s(0, 11));
1217    }
1218
1219    #[test]
1220    fn ast_types_are_clone_and_eq() {
1221        let id = Identifier::new("X", s(0, 1));
1222        let cloned = id.clone();
1223        assert_eq!(id, cloned);
1224    }
1225}