Skip to main content

sysml_v2_parser/
ast.rs

1//! Abstract syntax tree types for SysML v2 textual notation.
2
3/// Source location: byte offset, line, column, and length in the source file.
4/// Line and column are **1-based**. Use [`Span::to_lsp_range`] for 0-based LSP ranges.
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Span {
7    pub offset: usize,
8    pub line: u32,
9    pub column: usize,
10    pub len: usize,
11}
12
13impl Span {
14    /// Dummy span for tests or synthetic nodes (offset 0, line 1, column 1, len 0).
15    pub fn dummy() -> Self {
16        Self {
17            offset: 0,
18            line: 1,
19            column: 1,
20            len: 0,
21        }
22    }
23
24    /// LSP uses 0-based line and 0-based character. Returns (start_line, start_character, end_line, end_character).
25    pub fn to_lsp_range(&self) -> (u32, u32, u32, u32) {
26        let start_line = self.line.saturating_sub(1);
27        let start_char = self.column.saturating_sub(1);
28        let end_char = start_char.saturating_add(self.len);
29        (start_line, start_char as u32, start_line, end_char as u32)
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::Span;
36
37    #[test]
38    fn span_dummy() {
39        let s = Span::dummy();
40        assert_eq!(s.offset, 0);
41        assert_eq!(s.line, 1);
42        assert_eq!(s.column, 1);
43        assert_eq!(s.len, 0);
44    }
45}
46
47#[derive(Debug, Clone)]
48pub struct Node<T> {
49    pub span: Span,
50    pub value: T,
51}
52
53impl<T: PartialEq> PartialEq for Node<T> {
54    fn eq(&self, other: &Self) -> bool {
55        self.value == other.value
56    }
57}
58
59impl<T: Eq> Eq for Node<T> {}
60
61impl<T> Node<T> {
62    pub fn new(span: Span, value: T) -> Self {
63        Self { span, value }
64    }
65}
66
67impl<T> std::ops::Deref for Node<T> {
68    type Target = T;
69    fn deref(&self) -> &T {
70        &self.value
71    }
72}
73
74/// Trait for generic access to node source span (e.g. visitors).
75pub trait AstNode {
76    fn span(&self) -> Span;
77}
78
79impl<T> AstNode for Node<T> {
80    fn span(&self) -> Span {
81        self.span.clone()
82    }
83}
84
85/// Expression: literals, feature refs, member access, index, bracket/unit, etc.
86#[derive(Debug, Clone, PartialEq, Eq)]
87pub enum Expression {
88    LiteralInteger(i64),
89    LiteralReal(String),
90    LiteralString(String),
91    LiteralBoolean(bool),
92    /// Single name or qualified name.
93    FeatureRef(String),
94    /// base.member (e.g. engine.fuelCmdPort).
95    MemberAccess(Box<Node<Expression>>, String),
96    /// base#(index) e.g. frontWheel#(1).
97    Index {
98        base: Box<Node<Expression>>,
99        index: Box<Node<Expression>>,
100    },
101    /// [unit] e.g. [kg].
102    Bracket(Box<Node<Expression>>),
103    /// value [unit] e.g. 1750 [kg].
104    LiteralWithUnit {
105        value: Box<Node<Expression>>,
106        unit: Box<Node<Expression>>,
107    },
108    /// Binary infix operation e.g. `a >= b * c`, `x / y`.
109    BinaryOp {
110        op: String,
111        left: Box<Node<Expression>>,
112        right: Box<Node<Expression>>,
113    },
114    /// Unary prefix: + - ~ not
115    UnaryOp {
116        op: String,
117        operand: Box<Node<Expression>>,
118    },
119    /// Comma-separated sequence in parentheses, e.g. `(engine1, engine2)` for ordered composition values.
120    Tuple(Vec<Node<Expression>>),
121    /// KerML null or empty sequence ().
122    Null,
123}
124
125/// KerML top-level element: package, namespace, import, or library package (BNF RootNamespace = PackageBodyElement*).
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub enum RootElement {
128    Package(Node<Package>),
129    LibraryPackage(Node<LibraryPackage>),
130    Namespace(Node<NamespaceDecl>),
131    Import(Node<Import>),
132}
133
134/// KerML NamespaceDeclaration: `namespace` Identification NamespaceBody (same body structure as Package).
135#[derive(Debug, Clone, PartialEq, Eq)]
136pub struct NamespaceDecl {
137    pub identification: Identification,
138    pub body: PackageBody,
139}
140
141/// Root of a SysML/KerML document: a sequence of top-level package or namespace elements.
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct RootNamespace {
144    pub elements: Vec<Node<RootElement>>,
145}
146
147/// KerML ElementFilterMember: MemberPrefix? 'filter' condition ';'
148#[derive(Debug, Clone, PartialEq, Eq)]
149pub struct FilterMember {
150    pub visibility: Option<Visibility>,
151    pub condition: Node<Expression>,
152}
153
154/// Placeholder node inserted when resilient parsing skips malformed input.
155#[derive(Debug, Clone, PartialEq, Eq)]
156pub struct ParseErrorNode {
157    pub message: String,
158    pub code: String,
159    pub expected: Option<String>,
160    pub found: Option<String>,
161    pub suggestion: Option<String>,
162}
163
164/// Modeled KerML semantic declaration captured as package-level syntax.
165#[derive(Debug, Clone, PartialEq, Eq)]
166pub struct KermlSemanticDecl {
167    pub bnf_production: String,
168    pub text: String,
169}
170
171/// Modeled KerML feature declaration family (occurrence/expr/predicate/succession).
172#[derive(Debug, Clone, PartialEq, Eq)]
173pub struct KermlFeatureDecl {
174    pub bnf_production: String,
175    pub text: String,
176}
177
178/// Package-level KerML feature declaration captured as an explicit dedicated node.
179#[derive(Debug, Clone, PartialEq, Eq)]
180pub struct FeatureDecl {
181    pub keyword: String,
182    pub text: String,
183}
184
185/// Package-level KerML classifier declaration captured as an explicit dedicated node.
186#[derive(Debug, Clone, PartialEq, Eq)]
187pub struct ClassifierDecl {
188    pub keyword: String,
189    pub text: String,
190}
191
192/// Modeled extended SysML/KerML declaration family not yet represented by
193/// dedicated concrete nodes (e.g. concern/message style library declarations).
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct ExtendedLibraryDecl {
196    pub bnf_production: String,
197    pub text: String,
198}
199
200/// Top-level element inside a namespace or package body.
201#[derive(Debug, Clone, PartialEq, Eq)]
202pub enum PackageBodyElement {
203    Error(Node<ParseErrorNode>),
204    Doc(Node<DocComment>),
205    Comment(Node<CommentAnnotation>),
206    TextualRep(Node<TextualRepresentation>),
207    Filter(Node<FilterMember>),
208    Package(Node<Package>),
209    LibraryPackage(Node<LibraryPackage>),
210    Import(Node<Import>),
211    PartDef(Node<PartDef>),
212    PartUsage(Node<PartUsage>),
213    PortDef(Node<PortDef>),
214    InterfaceDef(Node<InterfaceDef>),
215    AliasDef(Node<AliasDef>),
216    AttributeDef(Node<AttributeDef>),
217    ActionDef(Node<ActionDef>),
218    ActionUsage(Node<ActionUsage>),
219    RequirementDef(Node<RequirementDef>),
220    RequirementUsage(Node<RequirementUsage>),
221    Satisfy(Node<Satisfy>),
222    UseCaseDef(Node<UseCaseDef>),
223    Actor(Node<ActorDecl>),
224    StateDef(Node<StateDef>),
225    StateUsage(Node<StateUsage>),
226    ItemDef(Node<ItemDef>),
227    IndividualDef(Node<IndividualDef>),
228    ConstraintDef(Node<ConstraintDef>),
229    CalcDef(Node<CalcDef>),
230    ViewDef(Node<ViewDef>),
231    ViewpointDef(Node<ViewpointDef>),
232    RenderingDef(Node<RenderingDef>),
233    ViewUsage(Node<ViewUsage>),
234    ViewpointUsage(Node<ViewpointUsage>),
235    RenderingUsage(Node<RenderingUsage>),
236    ConnectionDef(Node<ConnectionDef>),
237    MetadataDef(Node<MetadataDef>),
238    EnumDef(Node<EnumDef>),
239    OccurrenceDef(Node<OccurrenceDef>),
240    OccurrenceUsage(Node<OccurrenceUsage>),
241    Dependency(Node<Dependency>),
242    AllocationDef(Node<AllocationDef>),
243    AllocationUsage(Node<AllocationUsage>),
244    FlowDef(Node<FlowDef>),
245    FlowUsage(Node<FlowUsage>),
246    ConcernUsage(Node<ConcernUsage>),
247    CaseDef(Node<CaseDef>),
248    CaseUsage(Node<CaseUsage>),
249    AnalysisCaseDef(Node<AnalysisCaseDef>),
250    AnalysisCaseUsage(Node<AnalysisCaseUsage>),
251    VerificationCaseDef(Node<VerificationCaseDef>),
252    VerificationCaseUsage(Node<VerificationCaseUsage>),
253    UseCaseUsage(Node<UseCaseUsage>),
254    FeatureDecl(Node<FeatureDecl>),
255    ClassifierDecl(Node<ClassifierDecl>),
256    KermlSemanticDecl(Node<KermlSemanticDecl>),
257    KermlFeatureDecl(Node<KermlFeatureDecl>),
258    ExtendedLibraryDecl(Node<ExtendedLibraryDecl>),
259}
260
261/// A package declaration: `package` Identification PackageBody
262#[derive(Debug, Clone, PartialEq, Eq)]
263pub struct Package {
264    pub identification: Identification,
265    pub body: PackageBody,
266}
267
268/// Identification: optional short name in `< >`, optional name.
269/// BNF: ( '<' declaredShortName = NAME '>' )? ( declaredName = NAME )?
270#[derive(Debug, Clone, PartialEq, Eq)]
271pub struct Identification {
272    /// Short name inside `< ... >`, if present.
273    pub short_name: Option<String>,
274    /// Main declared name (may be quoted, e.g. '1a-Parts Tree').
275    pub name: Option<String>,
276}
277
278/// Package body: either `;` or `{` PackageBodyElement* `}`
279#[derive(Debug, Clone, PartialEq, Eq)]
280pub enum PackageBody {
281    /// Semicolon form: no body elements.
282    Semicolon,
283    /// Brace form: list of body elements (may be empty).
284    Brace {
285        elements: Vec<Node<PackageBodyElement>>,
286    },
287}
288
289/// Visibility for imports and members.
290#[derive(Debug, Clone, Copy, PartialEq, Eq)]
291pub enum Visibility {
292    Public,
293    Private,
294    Protected,
295}
296
297/// KerML FilterPackageMember: `[` OwnedExpression `]`.
298#[derive(Debug, Clone, PartialEq, Eq)]
299pub struct FilterPackageMember {
300    pub expression: Node<Expression>,
301}
302
303/// Import: `private`? `import` `all`? QualifiedName (`::` `*`)? or FilterPackage form.
304#[derive(Debug, Clone, PartialEq, Eq)]
305pub struct Import {
306    pub visibility: Option<Visibility>,
307    /// Whether this is a namespace import (QualifiedName::* or FilterPackage) or membership import (single QualifiedName).
308    pub is_import_all: bool,
309    /// Import target, e.g. "SI::kg" or "Definitions::*".
310    pub target: String,
311    /// KerML: optional recursive import after :: (e.g. QualifiedName::** or QualifiedName::*::**).
312    pub is_recursive: bool,
313    /// KerML FilterPackage form: one or more `[ expr ]` members. When present, this is a namespace import of a filter package.
314    pub filter_members: Option<Vec<Node<FilterPackageMember>>>,
315}
316
317/// Part definition: `part def` Identification (`:>` specializes)? Body.
318#[derive(Debug, Clone, PartialEq, Eq)]
319pub struct PartDef {
320    /// Optional `abstract` or `variation` prefix (BNF BasicDefinitionPrefix).
321    pub definition_prefix: Option<DefinitionPrefix>,
322    /// Whether this is an `individual part def`.
323    pub is_individual: bool,
324    pub identification: Identification,
325    /// Supertype after `:>`, e.g. Some("Axle") for `part def FrontAxle :> Axle`.
326    pub specializes: Option<String>,
327    /// Span of the `:> <type>` fragment (for semantic tokens), when present.
328    pub specializes_span: Option<Span>,
329    pub body: PartDefBody,
330}
331
332/// BNF BasicDefinitionPrefix: `abstract` | `variation`.
333#[derive(Debug, Clone, PartialEq, Eq)]
334pub enum DefinitionPrefix {
335    Abstract,
336    Variation,
337}
338
339/// Body of a part definition: `;` or `{` PartDefBodyElement* `}`.
340#[derive(Debug, Clone, PartialEq, Eq)]
341pub enum PartDefBody {
342    Semicolon,
343    Brace {
344        elements: Vec<Node<PartDefBodyElement>>,
345    },
346}
347
348/// Element inside a part definition body.
349#[derive(Debug, Clone, PartialEq, Eq)]
350pub enum PartDefBodyElement {
351    Error(Node<ParseErrorNode>),
352    Doc(Node<DocComment>),
353    Comment(Node<CommentAnnotation>),
354    Annotation(Node<Annotation>),
355    Other(String),
356    AttributeDef(Node<AttributeDef>),
357    AttributeUsage(Node<AttributeUsage>),
358    RequirementUsage(Node<RequirementUsage>),
359    Ref(Node<RefDecl>),
360    PortUsage(Node<PortUsage>),
361    PartUsage(Box<Node<PartUsage>>),
362    OccurrenceUsage(Box<Node<OccurrenceUsage>>),
363    InterfaceUsage(Node<InterfaceUsage>),
364    Connect(Node<Connect>),
365    /// `connection` usage member inside a part definition body.
366    Connection(Node<ConnectionUsageMember>),
367    Perform(Node<Perform>),
368    Allocate(Node<Allocate>),
369    OpaqueMember(Node<OpaqueMemberDecl>),
370    /// `exhibit state` name `:` type (`;` or body).
371    ExhibitState(Node<ExhibitState>),
372}
373
374/// Library-tolerant part member preserved without forcing it into an unrelated node shape.
375#[derive(Debug, Clone, PartialEq, Eq)]
376pub struct OpaqueMemberDecl {
377    pub keyword: String,
378    pub name: String,
379    pub text: String,
380    pub body: AttributeBody,
381}
382
383/// Connection usage member inside part definitions.
384#[derive(Debug, Clone, PartialEq, Eq)]
385pub struct ConnectionUsageMember {
386    pub name: Option<String>,
387    pub type_name: Option<String>,
388    pub body: ConnectionDefBody,
389    pub subsets: Option<String>,
390    pub redefines: Option<String>,
391}
392
393/// Exhibit state usage: `exhibit state` name `:` type (`;` or body).
394#[derive(Debug, Clone, PartialEq, Eq)]
395pub struct ExhibitState {
396    pub name: String,
397    pub type_name: Option<String>,
398    pub redefines: Option<String>,
399    pub body: StateDefBody,
400}
401
402/// Attribute definition: `attribute` name (`:>` type)? body.
403#[derive(Debug, Clone, PartialEq, Eq)]
404pub struct AttributeDef {
405    pub name: String,
406    /// Type after `:>`, e.g. Some("ISQ::mass").
407    pub typing: Option<String>,
408    pub body: AttributeBody,
409    /// Span of the defined name (for semantic tokens).
410    pub name_span: Option<Span>,
411    /// Span of the type after `:>`, if present (for semantic tokens).
412    pub typing_span: Option<Span>,
413}
414
415/// Body of an attribute (def or usage): `;` or `{` ... `}`.
416#[derive(Debug, Clone, PartialEq, Eq)]
417pub enum AttributeBody {
418    Semicolon,
419    Brace,
420}
421
422/// Item definition: `item def` Identification body (for events, etc.).
423#[derive(Debug, Clone, PartialEq, Eq)]
424pub struct ItemDef {
425    pub identification: Identification,
426    pub body: AttributeBody,
427}
428
429/// Individual definition: `individual def` Identification `:>` type body.
430#[derive(Debug, Clone, PartialEq, Eq)]
431pub struct IndividualDef {
432    pub identification: Identification,
433    pub specializes: Option<String>,
434    pub body: AttributeBody,
435}
436
437/// Part usage: `part` name `:` type multiplicity? `ordered`? (`redefines`|`:>>`)? value? body.
438#[derive(Debug, Clone, PartialEq, Eq)]
439pub struct PartUsage {
440    pub is_individual: bool,
441    pub name: String,
442    /// Type after `:`, e.g. "Vehicle", "AxleAssembly".
443    pub type_name: String,
444    /// Multiplicity, e.g. Some("[2]").
445    pub multiplicity: Option<String>,
446    pub ordered: bool,
447    /// Optional `subsets` feature and value expression.
448    pub subsets: Option<(String, Option<Node<Expression>>)>,
449    /// Redefines target, e.g. Some("frontAxleAssembly") or Some("vehicle1::mass").
450    pub redefines: Option<String>,
451    /// Value expression (= expr, default = expr, := expr).
452    pub value: Option<Node<Expression>>,
453    pub body: PartUsageBody,
454    /// Span of the usage name (for semantic tokens).
455    pub name_span: Option<Span>,
456    /// Span of the type reference after `:` (for semantic tokens).
457    pub type_ref_span: Option<Span>,
458}
459
460/// Body of a part usage: `;` or `{` PartUsageBodyElement* `}`.
461#[derive(Debug, Clone, PartialEq, Eq)]
462pub enum PartUsageBody {
463    Semicolon,
464    Brace {
465        elements: Vec<Node<PartUsageBodyElement>>,
466    },
467}
468
469/// Metadata annotation on usage: `@` Name (`:` Type)? MetadataBody (e.g. `@Security;` or `@Safety{isMandatory = true;}`).
470#[derive(Debug, Clone, PartialEq, Eq)]
471pub struct MetadataAnnotation {
472    pub name: String,
473    pub type_name: Option<String>,
474    pub body: ConnectBody,
475}
476
477/// Generic annotation or metadata usage captured in body scopes.
478#[derive(Debug, Clone, PartialEq, Eq)]
479pub struct Annotation {
480    pub sigil: String,
481    pub head: String,
482    pub type_name: Option<String>,
483    pub body: ConnectBody,
484}
485
486/// Element inside a part usage body.
487#[derive(Debug, Clone, PartialEq, Eq)]
488pub enum PartUsageBodyElement {
489    Error(Node<ParseErrorNode>),
490    Doc(Node<DocComment>),
491    Annotation(Node<Annotation>),
492    AttributeUsage(Node<AttributeUsage>),
493    PartUsage(Box<Node<PartUsage>>),
494    OccurrenceUsage(Box<Node<OccurrenceUsage>>),
495    PortUsage(Node<PortUsage>),
496    Bind(Node<Bind>),
497    /// `ref` name `:` type body (reference binding in part usage).
498    Ref(Node<RefDecl>),
499    InterfaceUsage(Node<InterfaceUsage>),
500    Connect(Node<Connect>),
501    Perform(Node<Perform>),
502    Allocate(Node<Allocate>),
503    Satisfy(Node<Satisfy>),
504    StateUsage(Node<StateUsage>),
505    MetadataAnnotation(Node<MetadataAnnotation>),
506}
507
508/// Enacted performance: `perform` action_path `{` body `}` inside a part usage.
509#[derive(Debug, Clone, PartialEq, Eq)]
510pub struct Perform {
511    /// Qualified action name (e.g. "provide power" or "provide power.generate torque").
512    pub action_name: String,
513    /// Type after `:` in "perform action name : Type" form.
514    pub type_name: Option<String>,
515    pub body: PerformBody,
516}
517
518/// Body of a perform: `;` or `{` PerformBodyElement* `}`.
519#[derive(Debug, Clone, PartialEq, Eq)]
520pub enum PerformBody {
521    Semicolon,
522    Brace {
523        elements: Vec<Node<PerformBodyElement>>,
524    },
525}
526
527/// Element inside a perform body: doc comment or in/out binding.
528#[derive(Debug, Clone, PartialEq, Eq)]
529pub enum PerformBodyElement {
530    Doc(Node<DocComment>),
531    InOut(Node<PerformInOutBinding>),
532}
533
534/// In/out binding inside a perform body: `in` name `=` expr `;` or `out` name `=` expr `;`.
535#[derive(Debug, Clone, PartialEq, Eq)]
536pub struct PerformInOutBinding {
537    pub direction: InOut,
538    pub name: String,
539    pub value: Node<Expression>,
540}
541
542/// Attribute usage: `attribute` name `redefines`? value? body.
543#[derive(Debug, Clone, PartialEq, Eq)]
544pub struct AttributeUsage {
545    pub name: String,
546    /// Redefines target, e.g. Some("Vehicle::mass").
547    pub redefines: Option<String>,
548    /// Value expression.
549    pub value: Option<Node<Expression>>,
550    pub body: AttributeBody,
551    /// Span of the usage name (for semantic tokens).
552    pub name_span: Option<Span>,
553    /// Span of the redefines target after `redefines`, if present (for semantic tokens).
554    pub redefines_span: Option<Span>,
555}
556
557// ---------------------------------------------------------------------------
558// Port
559// ---------------------------------------------------------------------------
560
561/// Port definition: `port def` Identification body.
562#[derive(Debug, Clone, PartialEq, Eq)]
563pub struct PortDef {
564    pub identification: Identification,
565    /// Supertype after `:>`, e.g. Some("ClutchPort") for `port def ManualClutchPort :> ClutchPort`.
566    pub specializes: Option<String>,
567    pub body: PortDefBody,
568}
569
570/// Body of a port definition: `;` or `{` PortDefBodyElement* `}`.
571#[derive(Debug, Clone, PartialEq, Eq)]
572pub enum PortDefBody {
573    Semicolon,
574    Brace {
575        elements: Vec<Node<PortDefBodyElement>>,
576    },
577}
578
579/// Element inside a port definition body (in/out declarations or nested port usages).
580#[derive(Debug, Clone, PartialEq, Eq)]
581pub enum PortDefBodyElement {
582    InOutDecl(Node<InOutDecl>),
583    Doc(Node<DocComment>),
584    AttributeDef(Node<AttributeDef>),
585    AttributeUsage(Node<AttributeUsage>),
586    PortUsage(Node<PortUsage>),
587}
588
589/// Port usage: `port` name `:` type multiplicity? `:>` subsets? `redefines`? body.
590#[derive(Debug, Clone, PartialEq, Eq)]
591pub struct PortUsage {
592    pub name: String,
593    pub type_name: Option<String>,
594    pub multiplicity: Option<String>,
595    /// Subsets feature and optional value expression.
596    pub subsets: Option<(String, Option<Node<Expression>>)>,
597    pub redefines: Option<String>,
598    pub body: PortBody,
599    /// Span of the usage name (for semantic tokens).
600    pub name_span: Option<Span>,
601    /// Span of the type reference after `:`, if present (for semantic tokens).
602    pub type_ref_span: Option<Span>,
603}
604
605/// Body of a port usage: `;` or `{` PortUsage* `}` (nested ports).
606#[derive(Debug, Clone, PartialEq, Eq)]
607pub enum PortBody {
608    Semicolon,
609    Brace,
610    /// Brace with nested port usages (e.g. port vehicleToRoadPort redefines ... { port left...; port right...; }).
611    BraceWithPorts {
612        elements: Vec<Node<PortUsage>>,
613    },
614}
615
616// ---------------------------------------------------------------------------
617// Interface
618// ---------------------------------------------------------------------------
619
620/// Interface definition: `interface def` Identification body.
621#[derive(Debug, Clone, PartialEq, Eq)]
622pub struct InterfaceDef {
623    pub identification: Identification,
624    pub body: InterfaceDefBody,
625}
626
627/// Body of an interface definition: `;` or `{` InterfaceDefBodyElement* `}`.
628#[derive(Debug, Clone, PartialEq, Eq)]
629pub enum InterfaceDefBody {
630    Semicolon,
631    Brace {
632        elements: Vec<Node<InterfaceDefBodyElement>>,
633    },
634}
635
636/// Element inside an interface definition body.
637#[derive(Debug, Clone, PartialEq, Eq)]
638pub enum InterfaceDefBodyElement {
639    Doc(Node<DocComment>),
640    EndDecl(Node<EndDecl>),
641    RefDecl(Node<RefDecl>),
642    ConnectStmt(Node<ConnectStmt>),
643}
644
645/// End declaration in interface def: `end` name `:` type `;`.
646#[derive(Debug, Clone, PartialEq, Eq)]
647pub struct EndDecl {
648    pub name: String,
649    pub type_name: String,
650    pub uses_derived_syntax: bool,
651    /// Span of the name (for semantic tokens).
652    pub name_span: Option<Span>,
653    /// Span of the type after `:` (for semantic tokens).
654    pub type_ref_span: Option<Span>,
655}
656
657/// Ref declaration in interface def: `ref` name `:` type body.
658#[derive(Debug, Clone, PartialEq, Eq)]
659pub struct RefDecl {
660    pub name: String,
661    pub type_name: String,
662    /// Optional binding value: `= expr` (SysML shorthand binding for references).
663    pub value: Option<Node<Expression>>,
664    pub body: RefBody,
665    /// Span of the name (for semantic tokens).
666    pub name_span: Option<Span>,
667    /// Span of the type after `:` (for semantic tokens).
668    pub type_ref_span: Option<Span>,
669}
670
671/// Body of a ref declaration: `;` or `{` ... `}`.
672#[derive(Debug, Clone, PartialEq, Eq)]
673pub enum RefBody {
674    Semicolon,
675    Brace,
676}
677
678// ---------------------------------------------------------------------------
679// Connection (Phase 2)
680// ---------------------------------------------------------------------------
681
682/// Connection definition: `connection def` Identification body (BNF ConnectionDefinition).
683#[derive(Debug, Clone, PartialEq, Eq)]
684pub struct ConnectionDef {
685    pub annotation: Option<String>,
686    pub identification: Identification,
687    pub body: ConnectionDefBody,
688}
689
690/// Body of a connection definition: `;` or `{` end/ref/connect* `}`.
691#[derive(Debug, Clone, PartialEq, Eq)]
692pub enum ConnectionDefBody {
693    Semicolon,
694    Brace {
695        elements: Vec<Node<ConnectionDefBodyElement>>,
696    },
697}
698
699#[derive(Debug, Clone, PartialEq, Eq)]
700pub enum ConnectionDefBodyElement {
701    EndDecl(Node<EndDecl>),
702    RefDecl(Node<RefDecl>),
703    ConnectStmt(Node<ConnectStmt>),
704}
705
706// ---------------------------------------------------------------------------
707// Metadata (Phase 2)
708// ---------------------------------------------------------------------------
709
710/// Metadata definition: `metadata def` Identification body (BNF MetadataDefinition).
711#[derive(Debug, Clone, PartialEq, Eq)]
712pub struct MetadataDef {
713    pub is_abstract: bool,
714    pub identification: Identification,
715    pub body: DefinitionBody,
716}
717
718// ---------------------------------------------------------------------------
719// Enumeration (Phase 2)
720// ---------------------------------------------------------------------------
721
722/// Enumeration definition: `enum def` Identification EnumerationBody (BNF EnumerationDefinition).
723#[derive(Debug, Clone, PartialEq, Eq)]
724pub struct EnumDef {
725    pub identification: Identification,
726    pub body: EnumerationBody,
727}
728
729#[derive(Debug, Clone, PartialEq, Eq)]
730pub enum EnumerationBody {
731    Semicolon,
732    Brace { values: Vec<String> },
733}
734
735// ---------------------------------------------------------------------------
736// Occurrence (Phase 2)
737// ---------------------------------------------------------------------------
738
739/// Occurrence definition: `occurrence def` Identification body (BNF OccurrenceDefinition).
740#[derive(Debug, Clone, PartialEq, Eq)]
741pub struct OccurrenceDef {
742    pub is_abstract: bool,
743    pub identification: Identification,
744    pub body: DefinitionBody,
745}
746
747/// Occurrence usage: `occurrence` name (`:` type)? body, with optional individual/portion modifiers.
748#[derive(Debug, Clone, PartialEq, Eq)]
749pub struct OccurrenceUsage {
750    pub is_individual: bool,
751    pub is_then: bool,
752    pub portion_kind: Option<String>,
753    pub name: String,
754    pub type_name: Option<String>,
755    pub subsets: Option<String>,
756    pub redefines: Option<String>,
757    pub body: OccurrenceUsageBody,
758}
759
760#[derive(Debug, Clone, PartialEq, Eq)]
761pub enum OccurrenceUsageBody {
762    Semicolon,
763    Brace {
764        elements: Vec<Node<OccurrenceBodyElement>>,
765    },
766}
767
768/// Occurrence-level assert member: `assert constraint` body.
769#[derive(Debug, Clone, PartialEq, Eq)]
770pub struct AssertConstraintMember {
771    pub body: ConstraintDefBody,
772}
773
774#[derive(Debug, Clone, PartialEq, Eq)]
775pub enum OccurrenceBodyElement {
776    Error(Node<ParseErrorNode>),
777    Doc(Node<DocComment>),
778    Annotation(Node<Annotation>),
779    AssertConstraint(Node<AssertConstraintMember>),
780    Other(String),
781    AttributeUsage(Node<AttributeUsage>),
782    PartUsage(Box<Node<PartUsage>>),
783    OccurrenceUsage(Box<Node<OccurrenceUsage>>),
784}
785
786// ---------------------------------------------------------------------------
787// Library Package (Phase 2)
788// ---------------------------------------------------------------------------
789
790/// Library package: `library` (optional `standard`) `package` Identification PackageBody (BNF LibraryPackage).
791#[derive(Debug, Clone, PartialEq, Eq)]
792pub struct LibraryPackage {
793    pub is_standard: bool,
794    pub identification: Identification,
795    pub body: PackageBody,
796}
797
798/// Generic definition body: `;` or `{` ... `}` (skip content for metadata/occurrence).
799#[derive(Debug, Clone, PartialEq, Eq)]
800pub enum DefinitionBody {
801    Semicolon,
802    Brace,
803}
804
805/// Connect statement in interface def or usage: `connect` from `to` to body.
806#[derive(Debug, Clone, PartialEq, Eq)]
807pub struct ConnectStmt {
808    pub from: Node<Expression>,
809    pub to: Node<Expression>,
810    pub body: ConnectBody,
811}
812
813/// Body of a connect statement: `;` or `{` ... `}`.
814#[derive(Debug, Clone, PartialEq, Eq)]
815pub enum ConnectBody {
816    Semicolon,
817    Brace,
818}
819
820// ---------------------------------------------------------------------------
821// Part usage body: bind, interface usage, connect
822// ---------------------------------------------------------------------------
823
824/// Bind: `bind` left `=` right (`;` or `{ }`).
825#[derive(Debug, Clone, PartialEq, Eq)]
826pub struct Bind {
827    pub left: Node<Expression>,
828    pub right: Node<Expression>,
829    /// Optional body after the bind (semicolon or brace); 3a fixture uses `bind x = y { }`.
830    pub body: Option<ConnectBody>,
831}
832
833/// Interface usage: typed+connect or connection form.
834#[derive(Debug, Clone, PartialEq, Eq)]
835pub enum InterfaceUsage {
836    /// `interface` `:Type`? `connect` from `to` to body; optional body with ref redefs.
837    TypedConnect {
838        interface_type: Option<String>,
839        from: Node<Expression>,
840        to: Node<Expression>,
841        body: ConnectBody,
842        body_elements: Vec<Node<InterfaceUsageBodyElement>>,
843    },
844    /// `interface` from `to` to body.
845    Connection {
846        from: Node<Expression>,
847        to: Node<Expression>,
848        body_elements: Vec<Node<InterfaceUsageBodyElement>>,
849    },
850}
851
852/// Element in interface usage body (e.g. ref redefinition).
853#[derive(Debug, Clone, PartialEq, Eq)]
854pub enum InterfaceUsageBodyElement {
855    /// `ref` `:>>` name `=` value body.
856    RefRedef {
857        name: String,
858        value: Node<Expression>,
859        body: RefBody,
860    },
861}
862
863/// Connect at part usage level: `connect` from `to` to body.
864#[derive(Debug, Clone, PartialEq, Eq)]
865pub struct Connect {
866    pub from: Node<Expression>,
867    pub to: Node<Expression>,
868    pub body: ConnectBody,
869}
870
871// ---------------------------------------------------------------------------
872// Alias
873// ---------------------------------------------------------------------------
874
875/// Alias definition: `alias` Identification `for` qualified_name body.
876#[derive(Debug, Clone, PartialEq, Eq)]
877pub struct AliasDef {
878    pub identification: Identification,
879    pub target: String,
880    pub body: AliasBody,
881}
882
883/// Body of an alias definition: `;` or `{` ... `}`.
884#[derive(Debug, Clone, PartialEq, Eq)]
885pub enum AliasBody {
886    Semicolon,
887    Brace,
888}
889
890// ---------------------------------------------------------------------------
891// Action (function-based behavior)
892// ---------------------------------------------------------------------------
893
894/// Action definition: `action def` Identification body (in/out params).
895#[derive(Debug, Clone, PartialEq, Eq)]
896pub struct ActionDef {
897    pub identification: Identification,
898    pub body: ActionDefBody,
899}
900
901/// Body of an action definition: `;` or `{` ActionDefBodyElement* `}`.
902#[derive(Debug, Clone, PartialEq, Eq)]
903pub enum ActionDefBody {
904    Semicolon,
905    Brace {
906        elements: Vec<Node<ActionDefBodyElement>>,
907    },
908}
909
910/// Element inside an action definition body.
911#[derive(Debug, Clone, PartialEq, Eq)]
912pub enum ActionDefBodyElement {
913    Error(Node<ParseErrorNode>),
914    InOutDecl(Node<InOutDecl>),
915    Doc(Node<DocComment>),
916    Annotation(Node<Annotation>),
917    RefDecl(Node<RefDecl>),
918    Perform(Node<Perform>),
919    Bind(Node<Bind>),
920    Flow(Node<Flow>),
921    FirstStmt(Node<FirstStmt>),
922    MergeStmt(Node<MergeStmt>),
923    StateUsage(Node<StateUsage>),
924    ActionUsage(Box<Node<ActionUsage>>),
925    Assign(Node<AssignStmt>),
926    ForLoop(Node<ForLoop>),
927    ThenAction(Node<ThenAction>),
928    Decl(Node<ActionBodyDecl>),
929}
930
931/// Assignment statement (SysML v2 AssignmentNode/AssignmentActionUsage).
932///
933/// Examples:
934/// - `assign x := y;`
935/// - `then assign position := dynamics.x_out;`
936#[derive(Debug, Clone, PartialEq, Eq)]
937pub struct AssignStmt {
938    pub is_then: bool,
939    pub lhs: String,
940    pub rhs: String,
941}
942
943/// For-loop node (SysML v2 ForLoopNode) - modeled minimally.
944#[derive(Debug, Clone, PartialEq, Eq)]
945pub struct ForLoop {
946    pub var: String,
947    pub range: String,
948    pub body: ActionDefBody,
949}
950
951/// Succession to an action usage: `then action ...`.
952#[derive(Debug, Clone, PartialEq, Eq)]
953pub struct ThenAction {
954    pub action: Node<ActionUsage>,
955}
956
957/// In/out parameter in action def: `in` name `:` type `;` or `out` name `:` type `;`.
958#[derive(Debug, Clone, PartialEq, Eq)]
959pub struct InOutDecl {
960    pub direction: InOut,
961    pub name: String,
962    pub type_name: String,
963}
964
965#[derive(Debug, Clone, Copy, PartialEq, Eq)]
966pub enum InOut {
967    In,
968    Out,
969    InOut,
970}
971
972/// Action usage: `action` name `:` type_name (`accept` param_name `:` param_type)? body.
973#[derive(Debug, Clone, PartialEq, Eq)]
974pub struct ActionUsage {
975    pub name: String,
976    pub type_name: String,
977    /// For accept form: (param_name, param_type).
978    pub accept: Option<(String, String)>,
979    pub body: ActionUsageBody,
980    /// Span of the usage name (for semantic tokens).
981    pub name_span: Option<Span>,
982    /// Span of the type reference after `:` (for semantic tokens).
983    pub type_ref_span: Option<Span>,
984}
985
986/// Body of an action usage: `;` or `{` ActionUsageBodyElement* `}`.
987#[derive(Debug, Clone, PartialEq, Eq)]
988pub enum ActionUsageBody {
989    Semicolon,
990    Brace {
991        elements: Vec<Node<ActionUsageBodyElement>>,
992    },
993}
994
995/// Element inside an action usage body.
996#[derive(Debug, Clone, PartialEq, Eq)]
997pub enum ActionUsageBodyElement {
998    Error(Node<ParseErrorNode>),
999    Doc(Node<DocComment>),
1000    Annotation(Node<Annotation>),
1001    InOutDecl(Node<InOutDecl>),
1002    RefDecl(Node<RefDecl>),
1003    Bind(Node<Bind>),
1004    Flow(Node<Flow>),
1005    FirstStmt(Node<FirstStmt>),
1006    MergeStmt(Node<MergeStmt>),
1007    StateUsage(Node<StateUsage>),
1008    ActionUsage(Box<Node<ActionUsage>>),
1009    Assign(Node<AssignStmt>),
1010    ForLoop(Node<ForLoop>),
1011    ThenAction(Node<ThenAction>),
1012    Decl(Node<ActionBodyDecl>),
1013}
1014
1015/// A minimally-modeled declaration inside an action/behavior body (e.g. `attribute ...;`, `calc ...;`).
1016#[derive(Debug, Clone, PartialEq, Eq)]
1017pub struct ActionBodyDecl {
1018    pub keyword: String,
1019    pub text: String,
1020}
1021
1022/// Flow: `flow` from `to` to body.
1023#[derive(Debug, Clone, PartialEq, Eq)]
1024pub struct Flow {
1025    pub from: Node<Expression>,
1026    pub to: Node<Expression>,
1027    pub body: ConnectBody,
1028}
1029
1030/// Flow definition: `flow def` Identification body.
1031#[derive(Debug, Clone, PartialEq, Eq)]
1032pub struct FlowDef {
1033    pub identification: Identification,
1034    pub body: DefinitionBody,
1035}
1036
1037/// Flow usage: `flow` name (`:` type)? [`from` expr `to` expr]? body.
1038#[derive(Debug, Clone, PartialEq, Eq)]
1039pub struct FlowUsage {
1040    pub name: String,
1041    pub type_name: Option<String>,
1042    pub from: Option<Node<Expression>>,
1043    pub to: Option<Node<Expression>>,
1044    pub body: DefinitionBody,
1045}
1046
1047/// First/then control flow: `first` expr `then` expr body.
1048#[derive(Debug, Clone, PartialEq, Eq)]
1049pub struct FirstStmt {
1050    pub first: Node<Expression>,
1051    pub then: Node<Expression>,
1052    pub body: FirstMergeBody,
1053}
1054
1055/// Merge: `merge` expr body.
1056#[derive(Debug, Clone, PartialEq, Eq)]
1057pub struct MergeStmt {
1058    pub merge: Node<Expression>,
1059    pub body: FirstMergeBody,
1060}
1061
1062/// Body of first/merge: `;` or `{` ... `}`.
1063#[derive(Debug, Clone, PartialEq, Eq)]
1064pub enum FirstMergeBody {
1065    Semicolon,
1066    Brace,
1067}
1068
1069// ---------------------------------------------------------------------------
1070// Allocation
1071// ---------------------------------------------------------------------------
1072
1073/// Allocate statement at part usage level: `allocate` from `to` to body.
1074#[derive(Debug, Clone, PartialEq, Eq)]
1075pub struct Allocate {
1076    pub source: Node<Expression>,
1077    pub target: Node<Expression>,
1078    pub body: ConnectBody,
1079}
1080
1081/// Allocation definition: `allocation def` Identification body.
1082#[derive(Debug, Clone, PartialEq, Eq)]
1083pub struct AllocationDef {
1084    pub identification: Identification,
1085    pub body: DefinitionBody,
1086}
1087
1088/// Allocation usage: `allocation` name (`:` type)? [`allocate` source `to` target]? body.
1089#[derive(Debug, Clone, PartialEq, Eq)]
1090pub struct AllocationUsage {
1091    pub name: String,
1092    pub type_name: Option<String>,
1093    pub source: Option<Node<Expression>>,
1094    pub target: Option<Node<Expression>>,
1095    pub body: DefinitionBody,
1096}
1097
1098// ---------------------------------------------------------------------------
1099// Requirements
1100// ---------------------------------------------------------------------------
1101
1102/// Requirement definition: `requirement def` Identification body.
1103#[derive(Debug, Clone, PartialEq, Eq)]
1104pub struct RequirementDef {
1105    pub identification: Identification,
1106    pub body: RequirementDefBody,
1107}
1108
1109/// Body of an requirement definition: `;` or `{` RequirementDefBodyElement* `}`.
1110#[derive(Debug, Clone, PartialEq, Eq)]
1111pub enum RequirementDefBody {
1112    Semicolon,
1113    Brace {
1114        elements: Vec<Node<RequirementDefBodyElement>>,
1115    },
1116}
1117
1118#[derive(Debug, Clone, PartialEq, Eq)]
1119pub enum RequirementDefBodyElement {
1120    Error(Node<ParseErrorNode>),
1121    /// Unmodeled requirement-body element captured as raw text (used for library parsing).
1122    Other(String),
1123    Annotation(Node<Annotation>),
1124    Import(Node<Import>),
1125    SubjectDecl(Node<SubjectDecl>),
1126    AttributeDef(Node<AttributeDef>),
1127    AttributeUsage(Node<AttributeUsage>),
1128    RequireConstraint(Node<RequireConstraint>),
1129    Frame(Node<FrameMember>),
1130    Doc(Node<DocComment>),
1131}
1132
1133/// Subject declaration: `subject` name `:` type `;`.
1134#[derive(Debug, Clone, PartialEq, Eq)]
1135pub struct SubjectDecl {
1136    pub name: String,
1137    pub type_name: String,
1138}
1139
1140/// Require constraint: `require constraint { ... }`.
1141#[derive(Debug, Clone, PartialEq, Eq)]
1142pub struct RequireConstraint {
1143    pub body: RequireConstraintBody,
1144}
1145
1146/// Require constraint body: `;` or `{` ConstraintDefBodyElement* `}`.
1147#[derive(Debug, Clone, PartialEq, Eq)]
1148pub enum RequireConstraintBody {
1149    Semicolon,
1150    Brace {
1151        elements: Vec<Node<ConstraintDefBodyElement>>,
1152    },
1153}
1154
1155/// Requirement usage / Satisfy. Example: `satisfy EnduranceReq by droneInstance;`
1156#[derive(Debug, Clone, PartialEq, Eq)]
1157pub struct Satisfy {
1158    pub source: Node<Expression>,
1159    pub target: Node<Expression>,
1160    pub body: ConnectBody,
1161}
1162
1163/// Bare requirement Usage.
1164#[derive(Debug, Clone, PartialEq, Eq)]
1165pub struct RequirementUsage {
1166    pub name: String,
1167    pub type_name: Option<String>,
1168    pub subsets: Option<String>,
1169    pub body: RequirementDefBody,
1170}
1171
1172/// Dependency: `dependency` (Identification `from`)? client(s) `to` supplier(s) RelationshipBody.
1173#[derive(Debug, Clone, PartialEq, Eq)]
1174pub struct Dependency {
1175    pub identification: Option<Identification>,
1176    pub clients: Vec<String>,
1177    pub suppliers: Vec<String>,
1178    pub body: ConnectBody,
1179}
1180
1181/// Framed concern member in requirement body: `frame` name (`;` or body).
1182#[derive(Debug, Clone, PartialEq, Eq)]
1183pub struct FrameMember {
1184    pub name: String,
1185    pub body: RequirementDefBody,
1186}
1187
1188/// Concern usage at package level: `concern` name (`:` type)? RequirementBody.
1189#[derive(Debug, Clone, PartialEq, Eq)]
1190pub struct ConcernUsage {
1191    pub name: String,
1192    pub type_name: Option<String>,
1193    pub body: RequirementDefBody,
1194}
1195
1196/// Case definition: `case def` Identification body.
1197#[derive(Debug, Clone, PartialEq, Eq)]
1198pub struct CaseDef {
1199    pub identification: Identification,
1200    pub body: UseCaseDefBody,
1201}
1202
1203/// Case usage: `case` name (`:` type)? body.
1204#[derive(Debug, Clone, PartialEq, Eq)]
1205pub struct CaseUsage {
1206    pub name: String,
1207    pub type_name: Option<String>,
1208    pub body: UseCaseDefBody,
1209}
1210
1211/// Analysis case definition: `analysis def` Identification body.
1212#[derive(Debug, Clone, PartialEq, Eq)]
1213pub struct AnalysisCaseDef {
1214    pub identification: Identification,
1215    pub body: UseCaseDefBody,
1216}
1217
1218/// Analysis case usage: `analysis` name (`:` type)? body.
1219#[derive(Debug, Clone, PartialEq, Eq)]
1220pub struct AnalysisCaseUsage {
1221    pub name: String,
1222    pub type_name: Option<String>,
1223    pub body: UseCaseDefBody,
1224}
1225
1226/// Verification case definition: `verification def` Identification body.
1227#[derive(Debug, Clone, PartialEq, Eq)]
1228pub struct VerificationCaseDef {
1229    pub identification: Identification,
1230    pub body: UseCaseDefBody,
1231}
1232
1233/// Verification case usage: `verification` name (`:` type)? body.
1234#[derive(Debug, Clone, PartialEq, Eq)]
1235pub struct VerificationCaseUsage {
1236    pub name: String,
1237    pub type_name: Option<String>,
1238    pub body: UseCaseDefBody,
1239}
1240
1241/// Use case usage at package level: `use case` name (`:` type)? CaseBody.
1242#[derive(Debug, Clone, PartialEq, Eq)]
1243pub struct UseCaseUsage {
1244    pub name: String,
1245    pub type_name: Option<String>,
1246    pub body: UseCaseDefBody,
1247}
1248
1249// ---------------------------------------------------------------------------
1250// Use Cases
1251// ---------------------------------------------------------------------------
1252
1253/// Actor declaration: `actor` Identification `;`.
1254#[derive(Debug, Clone, PartialEq, Eq)]
1255pub struct ActorDecl {
1256    pub identification: Identification,
1257}
1258
1259/// Use Case definition: `use case def` Identification body.
1260#[derive(Debug, Clone, PartialEq, Eq)]
1261pub struct UseCaseDef {
1262    pub identification: Identification,
1263    pub body: UseCaseDefBody,
1264}
1265
1266#[derive(Debug, Clone, PartialEq, Eq)]
1267pub enum UseCaseDefBody {
1268    Semicolon,
1269    Brace {
1270        elements: Vec<Node<UseCaseDefBodyElement>>,
1271    },
1272}
1273
1274/// `first <name>;` inside a case/use-case body (used in SysML v2 release fixtures).
1275#[derive(Debug, Clone, PartialEq, Eq)]
1276pub struct FirstSuccession {
1277    pub target: String,
1278}
1279
1280/// `then done;` inside a case/use-case body.
1281#[derive(Debug, Clone, PartialEq, Eq)]
1282pub struct ThenDone {}
1283
1284/// `include <usecase> ...` inside a case/use-case body.
1285#[derive(Debug, Clone, PartialEq, Eq)]
1286pub struct IncludeUseCase {
1287    pub name: String,
1288    /// Optional multiplicity suffix like `[0..*]` captured as raw text including brackets.
1289    pub multiplicity: Option<String>,
1290    pub body: UseCaseDefBody,
1291}
1292
1293/// `then include <usecase> ...` inside a case/use-case body.
1294#[derive(Debug, Clone, PartialEq, Eq)]
1295pub struct ThenIncludeUseCase {
1296    pub include: Node<IncludeUseCase>,
1297}
1298
1299/// `then use case <name> ...` inside a case/use-case body.
1300#[derive(Debug, Clone, PartialEq, Eq)]
1301pub struct ThenUseCaseUsage {
1302    pub use_case: Node<UseCaseUsage>,
1303}
1304
1305/// `subject;` shorthand used in SysML v2 release fixtures (subject of an enclosing case/use case).
1306#[derive(Debug, Clone, PartialEq, Eq)]
1307pub struct SubjectRef {}
1308
1309/// `actor :>> <name> = <expr>;` redefinition/assignment used in SysML v2 release fixtures.
1310#[derive(Debug, Clone, PartialEq, Eq)]
1311pub struct ActorRedefinitionAssignment {
1312    pub name: String,
1313    /// Raw RHS expression text up to `;` (we don't model the expression grammar here yet).
1314    pub rhs: String,
1315}
1316
1317/// `ref :>> <name> { ... }` redefinition used in SysML v2 release fixtures.
1318#[derive(Debug, Clone, PartialEq, Eq)]
1319pub struct RefRedefinition {
1320    pub name: String,
1321    /// Raw body text for now (balanced `{ ... }` including nested braces).
1322    pub body: String,
1323}
1324
1325/// `return ref <name><multiplicity?> { ... }` used in SysML v2 release libraries.
1326#[derive(Debug, Clone, PartialEq, Eq)]
1327pub struct ReturnRef {
1328    pub name: String,
1329    pub multiplicity: Option<String>,
1330    /// Raw body text for now (balanced `{ ... }` including nested braces).
1331    pub body: String,
1332}
1333
1334#[derive(Debug, Clone, PartialEq, Eq)]
1335pub enum UseCaseDefBodyElement {
1336    Error(Node<ParseErrorNode>),
1337    /// Unmodeled use-case / analysis-case body element captured as raw text (used for library parsing).
1338    Other(String),
1339    Doc(Node<DocComment>),
1340    SubjectDecl(Node<SubjectDecl>),
1341    /// `subject;` shorthand.
1342    SubjectRef(Node<SubjectRef>),
1343    ActorUsage(Node<ActorUsage>),
1344    ActorRedefinitionAssignment(Node<ActorRedefinitionAssignment>),
1345    Objective(Node<Objective>),
1346    FirstSuccession(Node<FirstSuccession>),
1347    ThenIncludeUseCase(Node<ThenIncludeUseCase>),
1348    ThenUseCaseUsage(Node<ThenUseCaseUsage>),
1349    ThenDone(Node<ThenDone>),
1350    IncludeUseCase(Node<IncludeUseCase>),
1351    RefRedefinition(Node<RefRedefinition>),
1352    ReturnRef(Node<ReturnRef>),
1353    Assign(Node<AssignStmt>),
1354    ForLoop(Node<ForLoop>),
1355    ThenAction(Node<ThenAction>),
1356}
1357
1358/// actor usage `actor pilot : Operator;`
1359#[derive(Debug, Clone, PartialEq, Eq)]
1360pub struct ActorUsage {
1361    pub name: String,
1362    pub type_name: String,
1363}
1364
1365/// Objective `objective { doc ... }`
1366#[derive(Debug, Clone, PartialEq, Eq)]
1367pub struct Objective {
1368    pub body: ConstraintBody,
1369}
1370
1371// ---------------------------------------------------------------------------
1372// State Machine
1373// ---------------------------------------------------------------------------
1374
1375/// State definition: `state def` Identification body.
1376#[derive(Debug, Clone, PartialEq, Eq)]
1377pub struct StateDef {
1378    pub identification: Identification,
1379    pub body: StateDefBody,
1380}
1381
1382#[derive(Debug, Clone, PartialEq, Eq)]
1383pub enum StateDefBody {
1384    Semicolon,
1385    Brace {
1386        elements: Vec<Node<StateDefBodyElement>>,
1387    },
1388}
1389
1390#[derive(Debug, Clone, PartialEq, Eq)]
1391pub enum StateDefBodyElement {
1392    Error(Node<ParseErrorNode>),
1393    Doc(Node<DocComment>),
1394    Annotation(Node<Annotation>),
1395    Other(String),
1396    /// `entry` (`;` or body) - entry action.
1397    Entry(Node<EntryAction>),
1398    /// `then` name `;` - initial state.
1399    Then(Node<ThenStmt>),
1400    /// `ref` name `:` type body – reference binding in state.
1401    Ref(Node<RefDecl>),
1402    RequirementUsage(Node<RequirementUsage>),
1403    StateUsage(Node<StateUsage>),
1404    Transition(Node<Transition>),
1405}
1406
1407/// Entry action: `entry` (`;` or body).
1408#[derive(Debug, Clone, PartialEq, Eq)]
1409pub struct EntryAction {
1410    /// For `entry action name body` form; None for plain `entry` body.
1411    pub action_name: Option<String>,
1412    pub body: StateDefBody,
1413}
1414
1415/// Then (initial state): `then` name `;`
1416#[derive(Debug, Clone, PartialEq, Eq)]
1417pub struct ThenStmt {
1418    pub state_name: String,
1419}
1420
1421/// State usage: `state` name (`:` type)? body.
1422#[derive(Debug, Clone, PartialEq, Eq)]
1423pub struct StateUsage {
1424    pub name: String,
1425    pub type_name: Option<String>,
1426    pub body: StateDefBody,
1427}
1428
1429/// Transition: `transition` name [`first` source] [`if` guard] [`do` effect] `then` target body.
1430#[derive(Debug, Clone, PartialEq, Eq)]
1431pub struct Transition {
1432    pub name: Option<String>,
1433    /// If omitted, form is `transition name then target;`.
1434    pub source: Option<Node<Expression>>,
1435    pub guard: Option<Node<Expression>>,
1436    pub effect: Option<Node<Expression>>,
1437    pub target: Node<Expression>,
1438    pub body: ConnectBody,
1439}
1440
1441// ---------------------------------------------------------------------------
1442// Constraints & Calculations
1443// ---------------------------------------------------------------------------
1444
1445/// Constraint definition: `constraint def` Identification body.
1446#[derive(Debug, Clone, PartialEq, Eq)]
1447pub struct ConstraintDef {
1448    pub identification: Identification,
1449    pub body: ConstraintDefBody,
1450}
1451
1452#[derive(Debug, Clone, PartialEq, Eq)]
1453pub enum ConstraintDefBody {
1454    Semicolon,
1455    Brace {
1456        elements: Vec<Node<ConstraintDefBodyElement>>,
1457    },
1458}
1459
1460#[derive(Debug, Clone, PartialEq, Eq)]
1461pub enum ConstraintDefBodyElement {
1462    Error(Node<ParseErrorNode>),
1463    Doc(Node<DocComment>),
1464    InOutDecl(Node<InOutDecl>),
1465    Expression(Node<Expression>), // e.g. totalThrust >= totalWeight * margin
1466    /// Unmodeled constraint-body element captured as raw text (used for library parsing).
1467    Other(String),
1468}
1469
1470/// constraint body {}
1471#[derive(Debug, Clone, PartialEq, Eq)]
1472pub enum ConstraintBody {
1473    Semicolon,
1474    Brace, // Often contains docs or block of expressions
1475}
1476
1477/// KerML Documentation: 'doc' Identification? ( 'locale' STRING_VALUE )? body = REGULAR_COMMENT.
1478#[derive(Debug, Clone, PartialEq, Eq)]
1479pub struct DocComment {
1480    /// Optional identification after 'doc'.
1481    pub identification: Option<Identification>,
1482    /// Optional locale string (e.g. "en").
1483    pub locale: Option<String>,
1484    /// Body text (content between /* and */).
1485    pub text: String,
1486}
1487
1488/// KerML Comment: ( 'comment' Identification? )? ( 'locale' STRING_VALUE )? body = REGULAR_COMMENT.
1489#[derive(Debug, Clone, PartialEq, Eq)]
1490pub struct CommentAnnotation {
1491    pub identification: Option<Identification>,
1492    pub locale: Option<String>,
1493    pub text: String,
1494}
1495
1496/// KerML TextualRepresentation: ( 'rep' Identification )? 'language' STRING_VALUE body.
1497#[derive(Debug, Clone, PartialEq, Eq)]
1498pub struct TextualRepresentation {
1499    pub rep_identification: Option<Identification>,
1500    pub language: String,
1501    pub text: String,
1502}
1503
1504/// Calc definition: `calc def` Identification body.
1505#[derive(Debug, Clone, PartialEq, Eq)]
1506pub struct CalcDef {
1507    pub identification: Identification,
1508    pub body: CalcDefBody,
1509}
1510
1511#[derive(Debug, Clone, PartialEq, Eq)]
1512pub enum CalcDefBody {
1513    Semicolon,
1514    Brace {
1515        elements: Vec<Node<CalcDefBodyElement>>,
1516    },
1517}
1518
1519#[derive(Debug, Clone, PartialEq, Eq)]
1520pub enum CalcDefBodyElement {
1521    Error(Node<ParseErrorNode>),
1522    Doc(Node<DocComment>),
1523    InOutDecl(Node<InOutDecl>),
1524    ReturnDecl(Node<ReturnDecl>),
1525    Expression(Node<Expression>), // formula
1526    /// Unmodeled calc-body element captured as raw text (used for library parsing).
1527    Other(String),
1528}
1529
1530/// Return declaration: `return` name `:` type `;`.
1531#[derive(Debug, Clone, PartialEq, Eq)]
1532pub struct ReturnDecl {
1533    pub name: String,
1534    pub type_name: String,
1535}
1536
1537// ---------------------------------------------------------------------------
1538// Views and Viewpoints (SysML v2 Clause 8.2.2.26)
1539// ---------------------------------------------------------------------------
1540
1541/// View definition: `view def` Identification ViewDefinitionBody.
1542#[derive(Debug, Clone, PartialEq, Eq)]
1543pub struct ViewDef {
1544    pub identification: Identification,
1545    pub body: ViewDefBody,
1546}
1547
1548#[derive(Debug, Clone, PartialEq, Eq)]
1549pub enum ViewDefBody {
1550    Semicolon,
1551    Brace {
1552        elements: Vec<Node<ViewDefBodyElement>>,
1553    },
1554}
1555
1556#[derive(Debug, Clone, PartialEq, Eq)]
1557pub enum ViewDefBodyElement {
1558    Error(Node<ParseErrorNode>),
1559    /// Unmodeled view-definition body element captured as raw text (used for library parsing).
1560    Other(String),
1561    Doc(Node<DocComment>),
1562    Filter(Node<FilterMember>),
1563    ViewRendering(Node<ViewRenderingUsage>),
1564}
1565
1566/// View rendering usage: `render` name `:` type (`;` or body).
1567#[derive(Debug, Clone, PartialEq, Eq)]
1568pub struct ViewRenderingUsage {
1569    pub name: String,
1570    pub type_name: Option<String>,
1571    pub body: ConnectBody,
1572}
1573
1574/// Viewpoint definition: `viewpoint def` Identification RequirementBody.
1575#[derive(Debug, Clone, PartialEq, Eq)]
1576pub struct ViewpointDef {
1577    pub identification: Identification,
1578    pub body: RequirementDefBody,
1579}
1580
1581/// Rendering definition: `rendering def` Definition.
1582#[derive(Debug, Clone, PartialEq, Eq)]
1583pub struct RenderingDef {
1584    pub identification: Identification,
1585    pub body: RenderingDefBody,
1586}
1587
1588#[derive(Debug, Clone, PartialEq, Eq)]
1589pub enum RenderingDefBody {
1590    Semicolon,
1591    Brace,
1592}
1593
1594/// View usage: `view` name `:` type? ViewBody.
1595#[derive(Debug, Clone, PartialEq, Eq)]
1596pub struct ViewUsage {
1597    pub name: String,
1598    pub type_name: Option<String>,
1599    pub body: ViewBody,
1600}
1601
1602#[derive(Debug, Clone, PartialEq, Eq)]
1603pub enum ViewBody {
1604    Semicolon,
1605    Brace {
1606        elements: Vec<Node<ViewBodyElement>>,
1607    },
1608}
1609
1610#[derive(Debug, Clone, PartialEq, Eq)]
1611pub enum ViewBodyElement {
1612    Error(Node<ParseErrorNode>),
1613    /// Unmodeled view body element captured as raw text (used for library parsing).
1614    Other(String),
1615    Doc(Node<DocComment>),
1616    Filter(Node<FilterMember>),
1617    ViewRendering(Node<ViewRenderingUsage>),
1618    Expose(Node<ExposeMember>),
1619    Satisfy(Node<SatisfyViewMember>),
1620}
1621
1622/// Expose in view body: `expose` (MembershipImport | NamespaceImport) RelationshipBody.
1623#[derive(Debug, Clone, PartialEq, Eq)]
1624pub struct ExposeMember {
1625    /// Full target path (e.g. vehicle, vehicle::*, vehicle::*::**, SystemModel::vehicle::**).
1626    pub target: String,
1627    pub body: ConnectBody,
1628}
1629
1630/// Satisfy in view body: `satisfy` QualifiedName RelationshipBody.
1631#[derive(Debug, Clone, PartialEq, Eq)]
1632pub struct SatisfyViewMember {
1633    pub viewpoint_ref: String,
1634    pub body: ConnectBody,
1635}
1636
1637/// Viewpoint usage: `viewpoint` ConstraintUsageDeclaration RequirementBody.
1638#[derive(Debug, Clone, PartialEq, Eq)]
1639pub struct ViewpointUsage {
1640    pub name: String,
1641    pub type_name: String,
1642    pub body: RequirementDefBody,
1643}
1644
1645/// Rendering usage: `rendering` Usage.
1646#[derive(Debug, Clone, PartialEq, Eq)]
1647pub struct RenderingUsage {
1648    pub name: String,
1649    pub type_name: Option<String>,
1650    pub body: ConnectBody,
1651}
1652
1653// ---------------------------------------------------------------------------
1654// Normalization for test comparison (strips optional spans so parsed == expected)
1655// ---------------------------------------------------------------------------
1656
1657impl RootNamespace {
1658    /// Returns a copy with all optional source spans set to `None` and all `Node` spans set to
1659    /// `Span::dummy()`. Use when comparing parser output to hand-built expected AST in tests.
1660    pub fn normalize_for_test_comparison(&self) -> Self {
1661        RootNamespace {
1662            elements: self
1663                .elements
1664                .iter()
1665                .map(normalize_root_element_node)
1666                .collect(),
1667        }
1668    }
1669}
1670
1671fn dummy_node<T: Clone>(_n: &Node<T>, value: T) -> Node<T> {
1672    Node::new(Span::dummy(), value)
1673}
1674
1675fn normalize_root_element_node(el: &Node<RootElement>) -> Node<RootElement> {
1676    let value = match &el.value {
1677        RootElement::Package(p) => RootElement::Package(dummy_node(p, normalize_package(&p.value))),
1678        RootElement::LibraryPackage(lp) => {
1679            RootElement::LibraryPackage(dummy_node(lp, normalize_library_package(&lp.value)))
1680        }
1681        RootElement::Namespace(n) => {
1682            RootElement::Namespace(dummy_node(n, normalize_namespace_decl(&n.value)))
1683        }
1684        RootElement::Import(n) => RootElement::Import(dummy_node(n, n.value.clone())),
1685    };
1686    dummy_node(el, value)
1687}
1688
1689fn normalize_library_package(lp: &LibraryPackage) -> LibraryPackage {
1690    LibraryPackage {
1691        is_standard: lp.is_standard,
1692        identification: lp.identification.clone(),
1693        body: normalize_package_body(&lp.body),
1694    }
1695}
1696
1697fn normalize_namespace_decl(n: &NamespaceDecl) -> NamespaceDecl {
1698    NamespaceDecl {
1699        identification: n.identification.clone(),
1700        body: normalize_package_body(&n.body),
1701    }
1702}
1703
1704fn normalize_package(p: &Package) -> Package {
1705    Package {
1706        identification: p.identification.clone(),
1707        body: normalize_package_body(&p.body),
1708    }
1709}
1710
1711fn normalize_package_body(b: &PackageBody) -> PackageBody {
1712    match b {
1713        PackageBody::Semicolon => PackageBody::Semicolon,
1714        PackageBody::Brace { elements } => PackageBody::Brace {
1715            elements: elements
1716                .iter()
1717                .map(normalize_package_body_element_node)
1718                .collect(),
1719        },
1720    }
1721}
1722
1723fn normalize_package_body_element_node(el: &Node<PackageBodyElement>) -> Node<PackageBodyElement> {
1724    let value = match &el.value {
1725        PackageBodyElement::Error(n) => PackageBodyElement::Error(dummy_node(n, n.value.clone())),
1726        PackageBodyElement::Doc(n) => PackageBodyElement::Doc(dummy_node(n, n.value.clone())),
1727        PackageBodyElement::Comment(n) => {
1728            PackageBodyElement::Comment(dummy_node(n, n.value.clone()))
1729        }
1730        PackageBodyElement::TextualRep(n) => {
1731            PackageBodyElement::TextualRep(dummy_node(n, n.value.clone()))
1732        }
1733        PackageBodyElement::Filter(n) => PackageBodyElement::Filter(dummy_node(n, n.value.clone())),
1734        PackageBodyElement::Package(n) => {
1735            PackageBodyElement::Package(dummy_node(n, normalize_package(&n.value)))
1736        }
1737        PackageBodyElement::LibraryPackage(n) => {
1738            PackageBodyElement::LibraryPackage(dummy_node(n, normalize_library_package(&n.value)))
1739        }
1740        PackageBodyElement::Import(n) => PackageBodyElement::Import(dummy_node(n, n.value.clone())),
1741        PackageBodyElement::PartDef(n) => {
1742            PackageBodyElement::PartDef(dummy_node(n, normalize_part_def(&n.value)))
1743        }
1744        PackageBodyElement::PartUsage(n) => {
1745            PackageBodyElement::PartUsage(dummy_node(n, normalize_part_usage(&n.value)))
1746        }
1747        PackageBodyElement::PortDef(n) => {
1748            PackageBodyElement::PortDef(dummy_node(n, normalize_port_def(&n.value)))
1749        }
1750        PackageBodyElement::InterfaceDef(n) => {
1751            PackageBodyElement::InterfaceDef(dummy_node(n, normalize_interface_def(&n.value)))
1752        }
1753        PackageBodyElement::ConnectionDef(n) => {
1754            PackageBodyElement::ConnectionDef(dummy_node(n, normalize_connection_def(&n.value)))
1755        }
1756        PackageBodyElement::MetadataDef(n) => {
1757            PackageBodyElement::MetadataDef(dummy_node(n, normalize_metadata_def(&n.value)))
1758        }
1759        PackageBodyElement::EnumDef(n) => {
1760            PackageBodyElement::EnumDef(dummy_node(n, normalize_enum_def(&n.value)))
1761        }
1762        PackageBodyElement::OccurrenceDef(n) => {
1763            PackageBodyElement::OccurrenceDef(dummy_node(n, normalize_occurrence_def(&n.value)))
1764        }
1765        PackageBodyElement::OccurrenceUsage(n) => {
1766            PackageBodyElement::OccurrenceUsage(dummy_node(n, n.value.clone()))
1767        }
1768        PackageBodyElement::AliasDef(n) => {
1769            PackageBodyElement::AliasDef(dummy_node(n, n.value.clone()))
1770        }
1771        PackageBodyElement::AttributeDef(n) => {
1772            PackageBodyElement::AttributeDef(dummy_node(n, normalize_attribute_def(&n.value)))
1773        }
1774        PackageBodyElement::ActionDef(n) => {
1775            PackageBodyElement::ActionDef(dummy_node(n, normalize_action_def(&n.value)))
1776        }
1777        PackageBodyElement::ActionUsage(n) => {
1778            PackageBodyElement::ActionUsage(dummy_node(n, normalize_action_usage(&n.value)))
1779        }
1780        PackageBodyElement::RequirementDef(n) => {
1781            PackageBodyElement::RequirementDef(dummy_node(n, n.value.clone()))
1782        }
1783        PackageBodyElement::RequirementUsage(n) => {
1784            PackageBodyElement::RequirementUsage(dummy_node(n, n.value.clone()))
1785        }
1786        PackageBodyElement::Satisfy(n) => {
1787            PackageBodyElement::Satisfy(dummy_node(n, n.value.clone()))
1788        }
1789        PackageBodyElement::UseCaseDef(n) => {
1790            PackageBodyElement::UseCaseDef(dummy_node(n, n.value.clone()))
1791        }
1792        PackageBodyElement::Actor(n) => PackageBodyElement::Actor(dummy_node(n, n.value.clone())),
1793        PackageBodyElement::StateDef(n) => {
1794            PackageBodyElement::StateDef(dummy_node(n, n.value.clone()))
1795        }
1796        PackageBodyElement::StateUsage(n) => {
1797            PackageBodyElement::StateUsage(dummy_node(n, n.value.clone()))
1798        }
1799        PackageBodyElement::ItemDef(n) => {
1800            PackageBodyElement::ItemDef(dummy_node(n, n.value.clone()))
1801        }
1802        PackageBodyElement::IndividualDef(n) => {
1803            PackageBodyElement::IndividualDef(dummy_node(n, n.value.clone()))
1804        }
1805        PackageBodyElement::ConstraintDef(n) => {
1806            PackageBodyElement::ConstraintDef(dummy_node(n, n.value.clone()))
1807        }
1808        PackageBodyElement::CalcDef(n) => {
1809            PackageBodyElement::CalcDef(dummy_node(n, n.value.clone()))
1810        }
1811        PackageBodyElement::ViewDef(n) => {
1812            PackageBodyElement::ViewDef(dummy_node(n, n.value.clone()))
1813        }
1814        PackageBodyElement::ViewpointDef(n) => {
1815            PackageBodyElement::ViewpointDef(dummy_node(n, n.value.clone()))
1816        }
1817        PackageBodyElement::RenderingDef(n) => {
1818            PackageBodyElement::RenderingDef(dummy_node(n, n.value.clone()))
1819        }
1820        PackageBodyElement::ViewUsage(n) => {
1821            PackageBodyElement::ViewUsage(dummy_node(n, n.value.clone()))
1822        }
1823        PackageBodyElement::ViewpointUsage(n) => {
1824            PackageBodyElement::ViewpointUsage(dummy_node(n, n.value.clone()))
1825        }
1826        PackageBodyElement::RenderingUsage(n) => {
1827            PackageBodyElement::RenderingUsage(dummy_node(n, n.value.clone()))
1828        }
1829        PackageBodyElement::Dependency(n) => {
1830            PackageBodyElement::Dependency(dummy_node(n, n.value.clone()))
1831        }
1832        PackageBodyElement::AllocationDef(n) => {
1833            PackageBodyElement::AllocationDef(dummy_node(n, n.value.clone()))
1834        }
1835        PackageBodyElement::AllocationUsage(n) => {
1836            PackageBodyElement::AllocationUsage(dummy_node(n, n.value.clone()))
1837        }
1838        PackageBodyElement::FlowDef(n) => {
1839            PackageBodyElement::FlowDef(dummy_node(n, n.value.clone()))
1840        }
1841        PackageBodyElement::FlowUsage(n) => {
1842            PackageBodyElement::FlowUsage(dummy_node(n, n.value.clone()))
1843        }
1844        PackageBodyElement::ConcernUsage(n) => {
1845            PackageBodyElement::ConcernUsage(dummy_node(n, n.value.clone()))
1846        }
1847        PackageBodyElement::CaseDef(n) => {
1848            PackageBodyElement::CaseDef(dummy_node(n, n.value.clone()))
1849        }
1850        PackageBodyElement::CaseUsage(n) => {
1851            PackageBodyElement::CaseUsage(dummy_node(n, n.value.clone()))
1852        }
1853        PackageBodyElement::AnalysisCaseDef(n) => {
1854            PackageBodyElement::AnalysisCaseDef(dummy_node(n, n.value.clone()))
1855        }
1856        PackageBodyElement::AnalysisCaseUsage(n) => {
1857            PackageBodyElement::AnalysisCaseUsage(dummy_node(n, n.value.clone()))
1858        }
1859        PackageBodyElement::VerificationCaseDef(n) => {
1860            PackageBodyElement::VerificationCaseDef(dummy_node(n, n.value.clone()))
1861        }
1862        PackageBodyElement::VerificationCaseUsage(n) => {
1863            PackageBodyElement::VerificationCaseUsage(dummy_node(n, n.value.clone()))
1864        }
1865        PackageBodyElement::UseCaseUsage(n) => {
1866            PackageBodyElement::UseCaseUsage(dummy_node(n, n.value.clone()))
1867        }
1868        PackageBodyElement::FeatureDecl(n) => {
1869            PackageBodyElement::FeatureDecl(dummy_node(n, n.value.clone()))
1870        }
1871        PackageBodyElement::ClassifierDecl(n) => {
1872            PackageBodyElement::ClassifierDecl(dummy_node(n, n.value.clone()))
1873        }
1874        PackageBodyElement::KermlSemanticDecl(n) => {
1875            PackageBodyElement::KermlSemanticDecl(dummy_node(n, n.value.clone()))
1876        }
1877        PackageBodyElement::KermlFeatureDecl(n) => {
1878            PackageBodyElement::KermlFeatureDecl(dummy_node(n, n.value.clone()))
1879        }
1880        PackageBodyElement::ExtendedLibraryDecl(n) => {
1881            PackageBodyElement::ExtendedLibraryDecl(dummy_node(n, n.value.clone()))
1882        }
1883    };
1884    dummy_node(el, value)
1885}
1886
1887fn normalize_attribute_def(a: &AttributeDef) -> AttributeDef {
1888    AttributeDef {
1889        name: a.name.clone(),
1890        typing: a.typing.clone(),
1891        body: a.body.clone(),
1892        name_span: None,
1893        typing_span: None,
1894    }
1895}
1896
1897fn normalize_part_def(p: &PartDef) -> PartDef {
1898    PartDef {
1899        definition_prefix: p.definition_prefix.clone(),
1900        is_individual: p.is_individual,
1901        identification: p.identification.clone(),
1902        specializes: p.specializes.clone(),
1903        specializes_span: None,
1904        body: normalize_part_def_body(&p.body),
1905    }
1906}
1907
1908fn normalize_part_def_body(b: &PartDefBody) -> PartDefBody {
1909    match b {
1910        PartDefBody::Semicolon => PartDefBody::Semicolon,
1911        PartDefBody::Brace { elements } => PartDefBody::Brace {
1912            elements: elements
1913                .iter()
1914                .map(normalize_part_def_body_element_node)
1915                .collect(),
1916        },
1917    }
1918}
1919
1920fn normalize_part_def_body_element_node(el: &Node<PartDefBodyElement>) -> Node<PartDefBodyElement> {
1921    let value = match &el.value {
1922        PartDefBodyElement::Error(n) => PartDefBodyElement::Error(dummy_node(n, n.value.clone())),
1923        PartDefBodyElement::Doc(n) => PartDefBodyElement::Doc(dummy_node(n, n.value.clone())),
1924        PartDefBodyElement::Comment(n) => {
1925            PartDefBodyElement::Comment(dummy_node(n, n.value.clone()))
1926        }
1927        PartDefBodyElement::Annotation(n) => {
1928            PartDefBodyElement::Annotation(dummy_node(n, n.value.clone()))
1929        }
1930        PartDefBodyElement::Other(text) => PartDefBodyElement::Other(text.clone()),
1931        PartDefBodyElement::AttributeDef(n) => {
1932            PartDefBodyElement::AttributeDef(dummy_node(n, normalize_attribute_def(&n.value)))
1933        }
1934        PartDefBodyElement::AttributeUsage(n) => {
1935            PartDefBodyElement::AttributeUsage(dummy_node(n, normalize_attribute_usage(&n.value)))
1936        }
1937        PartDefBodyElement::RequirementUsage(n) => {
1938            PartDefBodyElement::RequirementUsage(dummy_node(n, n.value.clone()))
1939        }
1940        PartDefBodyElement::Ref(n) => {
1941            PartDefBodyElement::Ref(dummy_node(n, normalize_ref_decl(&n.value)))
1942        }
1943        PartDefBodyElement::PortUsage(n) => {
1944            PartDefBodyElement::PortUsage(dummy_node(n, normalize_port_usage(&n.value)))
1945        }
1946        PartDefBodyElement::PartUsage(n) => {
1947            PartDefBodyElement::PartUsage(Box::new(dummy_node(n, normalize_part_usage(&n.value))))
1948        }
1949        PartDefBodyElement::OccurrenceUsage(n) => {
1950            PartDefBodyElement::OccurrenceUsage(Box::new(dummy_node(n, n.value.clone())))
1951        }
1952        PartDefBodyElement::InterfaceUsage(n) => {
1953            PartDefBodyElement::InterfaceUsage(dummy_node(n, n.value.clone()))
1954        }
1955        PartDefBodyElement::Connect(n) => {
1956            PartDefBodyElement::Connect(dummy_node(n, n.value.clone()))
1957        }
1958        PartDefBodyElement::Connection(n) => {
1959            PartDefBodyElement::Connection(dummy_node(n, n.value.clone()))
1960        }
1961        PartDefBodyElement::Perform(n) => {
1962            PartDefBodyElement::Perform(dummy_node(n, n.value.clone()))
1963        }
1964        PartDefBodyElement::Allocate(n) => {
1965            PartDefBodyElement::Allocate(dummy_node(n, n.value.clone()))
1966        }
1967        PartDefBodyElement::OpaqueMember(n) => {
1968            PartDefBodyElement::OpaqueMember(dummy_node(n, n.value.clone()))
1969        }
1970        PartDefBodyElement::ExhibitState(n) => {
1971            PartDefBodyElement::ExhibitState(dummy_node(n, n.value.clone()))
1972        }
1973    };
1974    dummy_node(el, value)
1975}
1976
1977fn normalize_attribute_usage(a: &AttributeUsage) -> AttributeUsage {
1978    AttributeUsage {
1979        name: a.name.clone(),
1980        redefines: a.redefines.clone(),
1981        value: a.value.clone(),
1982        body: a.body.clone(),
1983        name_span: None,
1984        redefines_span: None,
1985    }
1986}
1987
1988fn normalize_part_usage(p: &PartUsage) -> PartUsage {
1989    PartUsage {
1990        is_individual: p.is_individual,
1991        name: p.name.clone(),
1992        type_name: p.type_name.clone(),
1993        multiplicity: p.multiplicity.clone(),
1994        ordered: p.ordered,
1995        subsets: p.subsets.clone(),
1996        redefines: p.redefines.clone(),
1997        value: p.value.clone(),
1998        body: normalize_part_usage_body(&p.body),
1999        name_span: None,
2000        type_ref_span: None,
2001    }
2002}
2003
2004fn normalize_part_usage_body(b: &PartUsageBody) -> PartUsageBody {
2005    match b {
2006        PartUsageBody::Semicolon => PartUsageBody::Semicolon,
2007        PartUsageBody::Brace { elements } => PartUsageBody::Brace {
2008            elements: elements
2009                .iter()
2010                .map(normalize_part_usage_body_element_node)
2011                .collect(),
2012        },
2013    }
2014}
2015
2016fn normalize_perform(p: &Perform) -> Perform {
2017    Perform {
2018        action_name: p.action_name.clone(),
2019        type_name: p.type_name.clone(),
2020        body: normalize_perform_body(&p.body),
2021    }
2022}
2023
2024fn normalize_perform_body(b: &PerformBody) -> PerformBody {
2025    match b {
2026        PerformBody::Semicolon => PerformBody::Semicolon,
2027        PerformBody::Brace { elements } => PerformBody::Brace {
2028            elements: elements
2029                .iter()
2030                .map(normalize_perform_body_element_node)
2031                .collect(),
2032        },
2033    }
2034}
2035
2036fn normalize_perform_body_element_node(el: &Node<PerformBodyElement>) -> Node<PerformBodyElement> {
2037    let value = match &el.value {
2038        PerformBodyElement::Doc(n) => PerformBodyElement::Doc(dummy_node(n, n.value.clone())),
2039        PerformBodyElement::InOut(n) => PerformBodyElement::InOut(dummy_node(
2040            n,
2041            PerformInOutBinding {
2042                direction: n.value.direction,
2043                name: n.value.name.clone(),
2044                value: normalize_expression_node(&n.value.value),
2045            },
2046        )),
2047    };
2048    dummy_node(el, value)
2049}
2050
2051fn normalize_expression_node(node: &Node<Expression>) -> Node<Expression> {
2052    let value = match &node.value {
2053        Expression::LiteralInteger(x) => Expression::LiteralInteger(*x),
2054        Expression::LiteralReal(s) => Expression::LiteralReal(s.clone()),
2055        Expression::LiteralString(s) => Expression::LiteralString(s.clone()),
2056        Expression::LiteralBoolean(b) => Expression::LiteralBoolean(*b),
2057        Expression::FeatureRef(s) => Expression::FeatureRef(s.clone()),
2058        Expression::MemberAccess(base, member) => {
2059            Expression::MemberAccess(Box::new(normalize_expression_node(base)), member.clone())
2060        }
2061        Expression::Index { base, index } => Expression::Index {
2062            base: Box::new(normalize_expression_node(base)),
2063            index: Box::new(normalize_expression_node(index)),
2064        },
2065        Expression::Bracket(inner) => {
2066            Expression::Bracket(Box::new(normalize_expression_node(inner)))
2067        }
2068        Expression::LiteralWithUnit { value: v, unit } => Expression::LiteralWithUnit {
2069            value: Box::new(normalize_expression_node(v)),
2070            unit: Box::new(normalize_expression_node(unit)),
2071        },
2072        Expression::BinaryOp { op, left, right } => Expression::BinaryOp {
2073            op: op.clone(),
2074            left: Box::new(normalize_expression_node(left)),
2075            right: Box::new(normalize_expression_node(right)),
2076        },
2077        Expression::UnaryOp { op, operand } => Expression::UnaryOp {
2078            op: op.clone(),
2079            operand: Box::new(normalize_expression_node(operand)),
2080        },
2081        Expression::Tuple(items) => {
2082            Expression::Tuple(items.iter().map(normalize_expression_node).collect())
2083        }
2084        Expression::Null => Expression::Null,
2085    };
2086    Node::new(Span::dummy(), value)
2087}
2088
2089fn normalize_part_usage_body_element_node(
2090    el: &Node<PartUsageBodyElement>,
2091) -> Node<PartUsageBodyElement> {
2092    let value = match &el.value {
2093        PartUsageBodyElement::Error(n) => {
2094            PartUsageBodyElement::Error(dummy_node(n, n.value.clone()))
2095        }
2096        PartUsageBodyElement::Doc(n) => PartUsageBodyElement::Doc(dummy_node(n, n.value.clone())),
2097        PartUsageBodyElement::Annotation(n) => {
2098            PartUsageBodyElement::Annotation(dummy_node(n, n.value.clone()))
2099        }
2100        PartUsageBodyElement::AttributeUsage(n) => {
2101            PartUsageBodyElement::AttributeUsage(dummy_node(n, normalize_attribute_usage(&n.value)))
2102        }
2103        PartUsageBodyElement::PartUsage(n) => {
2104            PartUsageBodyElement::PartUsage(Box::new(dummy_node(n, normalize_part_usage(&n.value))))
2105        }
2106        PartUsageBodyElement::OccurrenceUsage(n) => {
2107            PartUsageBodyElement::OccurrenceUsage(Box::new(dummy_node(n, n.value.clone())))
2108        }
2109        PartUsageBodyElement::PortUsage(n) => {
2110            PartUsageBodyElement::PortUsage(dummy_node(n, normalize_port_usage(&n.value)))
2111        }
2112        PartUsageBodyElement::Ref(n) => {
2113            PartUsageBodyElement::Ref(dummy_node(n, normalize_ref_decl(&n.value)))
2114        }
2115        PartUsageBodyElement::Bind(n) => PartUsageBodyElement::Bind(dummy_node(n, n.value.clone())),
2116        PartUsageBodyElement::InterfaceUsage(n) => {
2117            PartUsageBodyElement::InterfaceUsage(dummy_node(n, n.value.clone()))
2118        }
2119        PartUsageBodyElement::Connect(n) => {
2120            PartUsageBodyElement::Connect(dummy_node(n, n.value.clone()))
2121        }
2122        PartUsageBodyElement::Perform(n) => {
2123            PartUsageBodyElement::Perform(dummy_node(n, normalize_perform(&n.value)))
2124        }
2125        PartUsageBodyElement::Allocate(n) => {
2126            PartUsageBodyElement::Allocate(dummy_node(n, n.value.clone()))
2127        }
2128        PartUsageBodyElement::Satisfy(n) => {
2129            PartUsageBodyElement::Satisfy(dummy_node(n, n.value.clone()))
2130        }
2131        PartUsageBodyElement::StateUsage(n) => {
2132            PartUsageBodyElement::StateUsage(dummy_node(n, n.value.clone()))
2133        }
2134        PartUsageBodyElement::MetadataAnnotation(n) => {
2135            PartUsageBodyElement::MetadataAnnotation(dummy_node(n, n.value.clone()))
2136        }
2137    };
2138    dummy_node(el, value)
2139}
2140
2141fn normalize_port_usage(p: &PortUsage) -> PortUsage {
2142    PortUsage {
2143        name: p.name.clone(),
2144        type_name: p.type_name.clone(),
2145        multiplicity: p.multiplicity.clone(),
2146        subsets: p.subsets.clone(),
2147        redefines: p.redefines.clone(),
2148        body: normalize_port_body(&p.body),
2149        name_span: None,
2150        type_ref_span: None,
2151    }
2152}
2153
2154fn normalize_port_body(b: &PortBody) -> PortBody {
2155    match b {
2156        PortBody::Semicolon => PortBody::Semicolon,
2157        PortBody::Brace => PortBody::Brace,
2158        PortBody::BraceWithPorts { elements } => PortBody::BraceWithPorts {
2159            elements: elements
2160                .iter()
2161                .map(|n| dummy_node(n, normalize_port_usage(&n.value)))
2162                .collect(),
2163        },
2164    }
2165}
2166
2167fn normalize_port_def(p: &PortDef) -> PortDef {
2168    PortDef {
2169        identification: p.identification.clone(),
2170        specializes: p.specializes.clone(),
2171        body: normalize_port_def_body(&p.body),
2172    }
2173}
2174
2175fn normalize_port_def_body(b: &PortDefBody) -> PortDefBody {
2176    match b {
2177        PortDefBody::Semicolon => PortDefBody::Semicolon,
2178        PortDefBody::Brace { elements } => PortDefBody::Brace {
2179            elements: elements
2180                .iter()
2181                .map(normalize_port_def_body_element_node)
2182                .collect(),
2183        },
2184    }
2185}
2186
2187fn normalize_port_def_body_element_node(el: &Node<PortDefBodyElement>) -> Node<PortDefBodyElement> {
2188    let value = match &el.value {
2189        PortDefBodyElement::InOutDecl(n) => {
2190            PortDefBodyElement::InOutDecl(dummy_node(n, n.value.clone()))
2191        }
2192        PortDefBodyElement::Doc(n) => PortDefBodyElement::Doc(dummy_node(n, n.value.clone())),
2193        PortDefBodyElement::AttributeDef(n) => {
2194            PortDefBodyElement::AttributeDef(dummy_node(n, normalize_attribute_def(&n.value)))
2195        }
2196        PortDefBodyElement::AttributeUsage(n) => {
2197            PortDefBodyElement::AttributeUsage(dummy_node(n, normalize_attribute_usage(&n.value)))
2198        }
2199        PortDefBodyElement::PortUsage(n) => {
2200            PortDefBodyElement::PortUsage(dummy_node(n, normalize_port_usage(&n.value)))
2201        }
2202    };
2203    dummy_node(el, value)
2204}
2205
2206fn normalize_interface_def(i: &InterfaceDef) -> InterfaceDef {
2207    InterfaceDef {
2208        identification: i.identification.clone(),
2209        body: normalize_interface_def_body(&i.body),
2210    }
2211}
2212
2213fn normalize_connection_def(c: &ConnectionDef) -> ConnectionDef {
2214    ConnectionDef {
2215        annotation: c.annotation.clone(),
2216        identification: c.identification.clone(),
2217        body: normalize_connection_def_body(&c.body),
2218    }
2219}
2220
2221fn normalize_connection_def_body(b: &ConnectionDefBody) -> ConnectionDefBody {
2222    match b {
2223        ConnectionDefBody::Semicolon => ConnectionDefBody::Semicolon,
2224        ConnectionDefBody::Brace { elements } => ConnectionDefBody::Brace {
2225            elements: elements
2226                .iter()
2227                .map(normalize_connection_def_body_element_node)
2228                .collect(),
2229        },
2230    }
2231}
2232
2233fn normalize_connection_def_body_element_node(
2234    el: &Node<ConnectionDefBodyElement>,
2235) -> Node<ConnectionDefBodyElement> {
2236    let value = match &el.value {
2237        ConnectionDefBodyElement::EndDecl(n) => {
2238            ConnectionDefBodyElement::EndDecl(dummy_node(n, normalize_end_decl(&n.value)))
2239        }
2240        ConnectionDefBodyElement::RefDecl(n) => {
2241            ConnectionDefBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2242        }
2243        ConnectionDefBodyElement::ConnectStmt(n) => {
2244            ConnectionDefBodyElement::ConnectStmt(dummy_node(n, n.value.clone()))
2245        }
2246    };
2247    dummy_node(el, value)
2248}
2249
2250fn normalize_metadata_def(m: &MetadataDef) -> MetadataDef {
2251    MetadataDef {
2252        is_abstract: m.is_abstract,
2253        identification: m.identification.clone(),
2254        body: m.body.clone(),
2255    }
2256}
2257
2258fn normalize_enum_def(e: &EnumDef) -> EnumDef {
2259    EnumDef {
2260        identification: e.identification.clone(),
2261        body: e.body.clone(),
2262    }
2263}
2264
2265fn normalize_occurrence_def(o: &OccurrenceDef) -> OccurrenceDef {
2266    OccurrenceDef {
2267        is_abstract: o.is_abstract,
2268        identification: o.identification.clone(),
2269        body: o.body.clone(),
2270    }
2271}
2272
2273fn normalize_interface_def_body(b: &InterfaceDefBody) -> InterfaceDefBody {
2274    match b {
2275        InterfaceDefBody::Semicolon => InterfaceDefBody::Semicolon,
2276        InterfaceDefBody::Brace { elements } => InterfaceDefBody::Brace {
2277            elements: elements
2278                .iter()
2279                .map(normalize_interface_def_body_element_node)
2280                .collect(),
2281        },
2282    }
2283}
2284
2285fn normalize_interface_def_body_element_node(
2286    el: &Node<InterfaceDefBodyElement>,
2287) -> Node<InterfaceDefBodyElement> {
2288    let value = match &el.value {
2289        InterfaceDefBodyElement::Doc(n) => {
2290            InterfaceDefBodyElement::Doc(dummy_node(n, n.value.clone()))
2291        }
2292        InterfaceDefBodyElement::EndDecl(n) => {
2293            InterfaceDefBodyElement::EndDecl(dummy_node(n, normalize_end_decl(&n.value)))
2294        }
2295        InterfaceDefBodyElement::RefDecl(n) => {
2296            InterfaceDefBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2297        }
2298        InterfaceDefBodyElement::ConnectStmt(n) => {
2299            InterfaceDefBodyElement::ConnectStmt(dummy_node(n, n.value.clone()))
2300        }
2301    };
2302    dummy_node(el, value)
2303}
2304
2305fn normalize_end_decl(e: &EndDecl) -> EndDecl {
2306    EndDecl {
2307        name: e.name.clone(),
2308        type_name: e.type_name.clone(),
2309        uses_derived_syntax: e.uses_derived_syntax,
2310        name_span: None,
2311        type_ref_span: None,
2312    }
2313}
2314
2315fn normalize_ref_decl(r: &RefDecl) -> RefDecl {
2316    RefDecl {
2317        name: r.name.clone(),
2318        type_name: r.type_name.clone(),
2319        value: r.value.clone(),
2320        body: r.body.clone(),
2321        name_span: None,
2322        type_ref_span: None,
2323    }
2324}
2325
2326fn normalize_action_def(a: &ActionDef) -> ActionDef {
2327    ActionDef {
2328        identification: a.identification.clone(),
2329        body: normalize_action_def_body(&a.body),
2330    }
2331}
2332
2333fn normalize_action_def_body(b: &ActionDefBody) -> ActionDefBody {
2334    match b {
2335        ActionDefBody::Semicolon => ActionDefBody::Semicolon,
2336        ActionDefBody::Brace { elements } => ActionDefBody::Brace {
2337            elements: elements
2338                .iter()
2339                .map(normalize_action_def_body_element_node)
2340                .collect(),
2341        },
2342    }
2343}
2344
2345fn normalize_action_def_body_element_node(
2346    el: &Node<ActionDefBodyElement>,
2347) -> Node<ActionDefBodyElement> {
2348    let value = match &el.value {
2349        ActionDefBodyElement::Error(n) => {
2350            ActionDefBodyElement::Error(dummy_node(n, n.value.clone()))
2351        }
2352        ActionDefBodyElement::InOutDecl(n) => {
2353            ActionDefBodyElement::InOutDecl(dummy_node(n, n.value.clone()))
2354        }
2355        ActionDefBodyElement::Doc(n) => ActionDefBodyElement::Doc(dummy_node(n, n.value.clone())),
2356        ActionDefBodyElement::Annotation(n) => {
2357            ActionDefBodyElement::Annotation(dummy_node(n, n.value.clone()))
2358        }
2359        ActionDefBodyElement::RefDecl(n) => {
2360            ActionDefBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2361        }
2362        ActionDefBodyElement::Perform(n) => {
2363            ActionDefBodyElement::Perform(dummy_node(n, normalize_perform(&n.value)))
2364        }
2365        ActionDefBodyElement::Bind(n) => ActionDefBodyElement::Bind(dummy_node(n, n.value.clone())),
2366        ActionDefBodyElement::Flow(n) => ActionDefBodyElement::Flow(dummy_node(n, n.value.clone())),
2367        ActionDefBodyElement::FirstStmt(n) => {
2368            ActionDefBodyElement::FirstStmt(dummy_node(n, n.value.clone()))
2369        }
2370        ActionDefBodyElement::MergeStmt(n) => {
2371            ActionDefBodyElement::MergeStmt(dummy_node(n, n.value.clone()))
2372        }
2373        ActionDefBodyElement::StateUsage(n) => {
2374            ActionDefBodyElement::StateUsage(dummy_node(n, n.value.clone()))
2375        }
2376        ActionDefBodyElement::ActionUsage(n) => ActionDefBodyElement::ActionUsage(Box::new(
2377            dummy_node(n, normalize_action_usage(&n.value)),
2378        )),
2379        ActionDefBodyElement::Assign(n) => {
2380            ActionDefBodyElement::Assign(dummy_node(n, n.value.clone()))
2381        }
2382        ActionDefBodyElement::ForLoop(n) => {
2383            ActionDefBodyElement::ForLoop(dummy_node(n, n.value.clone()))
2384        }
2385        ActionDefBodyElement::ThenAction(n) => {
2386            ActionDefBodyElement::ThenAction(dummy_node(n, n.value.clone()))
2387        }
2388        ActionDefBodyElement::Decl(n) => ActionDefBodyElement::Decl(dummy_node(n, n.value.clone())),
2389    };
2390    dummy_node(el, value)
2391}
2392
2393fn normalize_action_usage(a: &ActionUsage) -> ActionUsage {
2394    ActionUsage {
2395        name: a.name.clone(),
2396        type_name: a.type_name.clone(),
2397        accept: a.accept.clone(),
2398        body: normalize_action_usage_body(&a.body),
2399        name_span: None,
2400        type_ref_span: None,
2401    }
2402}
2403
2404fn normalize_action_usage_body(b: &ActionUsageBody) -> ActionUsageBody {
2405    match b {
2406        ActionUsageBody::Semicolon => ActionUsageBody::Semicolon,
2407        ActionUsageBody::Brace { elements } => ActionUsageBody::Brace {
2408            elements: elements
2409                .iter()
2410                .map(normalize_action_usage_body_element_node)
2411                .collect(),
2412        },
2413    }
2414}
2415
2416fn normalize_action_usage_body_element_node(
2417    el: &Node<ActionUsageBodyElement>,
2418) -> Node<ActionUsageBodyElement> {
2419    let value = match &el.value {
2420        ActionUsageBodyElement::Error(n) => {
2421            ActionUsageBodyElement::Error(dummy_node(n, n.value.clone()))
2422        }
2423        ActionUsageBodyElement::Doc(n) => {
2424            ActionUsageBodyElement::Doc(dummy_node(n, n.value.clone()))
2425        }
2426        ActionUsageBodyElement::Annotation(n) => {
2427            ActionUsageBodyElement::Annotation(dummy_node(n, n.value.clone()))
2428        }
2429        ActionUsageBodyElement::InOutDecl(n) => {
2430            ActionUsageBodyElement::InOutDecl(dummy_node(n, n.value.clone()))
2431        }
2432        ActionUsageBodyElement::RefDecl(n) => {
2433            ActionUsageBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2434        }
2435        ActionUsageBodyElement::Bind(n) => {
2436            ActionUsageBodyElement::Bind(dummy_node(n, n.value.clone()))
2437        }
2438        ActionUsageBodyElement::Flow(n) => {
2439            ActionUsageBodyElement::Flow(dummy_node(n, n.value.clone()))
2440        }
2441        ActionUsageBodyElement::FirstStmt(n) => {
2442            ActionUsageBodyElement::FirstStmt(dummy_node(n, n.value.clone()))
2443        }
2444        ActionUsageBodyElement::MergeStmt(n) => {
2445            ActionUsageBodyElement::MergeStmt(dummy_node(n, n.value.clone()))
2446        }
2447        ActionUsageBodyElement::StateUsage(n) => {
2448            ActionUsageBodyElement::StateUsage(dummy_node(n, n.value.clone()))
2449        }
2450        ActionUsageBodyElement::ActionUsage(n) => ActionUsageBodyElement::ActionUsage(Box::new(
2451            dummy_node(n, normalize_action_usage(&n.value)),
2452        )),
2453        ActionUsageBodyElement::Assign(n) => {
2454            ActionUsageBodyElement::Assign(dummy_node(n, n.value.clone()))
2455        }
2456        ActionUsageBodyElement::ForLoop(n) => {
2457            ActionUsageBodyElement::ForLoop(dummy_node(n, n.value.clone()))
2458        }
2459        ActionUsageBodyElement::ThenAction(n) => {
2460            ActionUsageBodyElement::ThenAction(dummy_node(n, n.value.clone()))
2461        }
2462        ActionUsageBodyElement::Decl(n) => {
2463            ActionUsageBodyElement::Decl(dummy_node(n, n.value.clone()))
2464        }
2465    };
2466    dummy_node(el, value)
2467}