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) => PartDefBodyElement::Comment(dummy_node(n, n.value.clone())),
1925        PartDefBodyElement::Annotation(n) => {
1926            PartDefBodyElement::Annotation(dummy_node(n, n.value.clone()))
1927        }
1928        PartDefBodyElement::Other(text) => PartDefBodyElement::Other(text.clone()),
1929        PartDefBodyElement::AttributeDef(n) => {
1930            PartDefBodyElement::AttributeDef(dummy_node(n, normalize_attribute_def(&n.value)))
1931        }
1932        PartDefBodyElement::AttributeUsage(n) => {
1933            PartDefBodyElement::AttributeUsage(dummy_node(n, normalize_attribute_usage(&n.value)))
1934        }
1935        PartDefBodyElement::RequirementUsage(n) => {
1936            PartDefBodyElement::RequirementUsage(dummy_node(n, n.value.clone()))
1937        }
1938        PartDefBodyElement::Ref(n) => {
1939            PartDefBodyElement::Ref(dummy_node(n, normalize_ref_decl(&n.value)))
1940        }
1941        PartDefBodyElement::PortUsage(n) => {
1942            PartDefBodyElement::PortUsage(dummy_node(n, normalize_port_usage(&n.value)))
1943        }
1944        PartDefBodyElement::PartUsage(n) => {
1945            PartDefBodyElement::PartUsage(Box::new(dummy_node(n, normalize_part_usage(&n.value))))
1946        }
1947        PartDefBodyElement::OccurrenceUsage(n) => {
1948            PartDefBodyElement::OccurrenceUsage(Box::new(dummy_node(n, n.value.clone())))
1949        }
1950        PartDefBodyElement::InterfaceUsage(n) => {
1951            PartDefBodyElement::InterfaceUsage(dummy_node(n, n.value.clone()))
1952        }
1953        PartDefBodyElement::Connect(n) => {
1954            PartDefBodyElement::Connect(dummy_node(n, n.value.clone()))
1955        }
1956        PartDefBodyElement::Connection(n) => {
1957            PartDefBodyElement::Connection(dummy_node(n, n.value.clone()))
1958        }
1959        PartDefBodyElement::Perform(n) => {
1960            PartDefBodyElement::Perform(dummy_node(n, n.value.clone()))
1961        }
1962        PartDefBodyElement::Allocate(n) => {
1963            PartDefBodyElement::Allocate(dummy_node(n, n.value.clone()))
1964        }
1965        PartDefBodyElement::OpaqueMember(n) => {
1966            PartDefBodyElement::OpaqueMember(dummy_node(n, n.value.clone()))
1967        }
1968        PartDefBodyElement::ExhibitState(n) => {
1969            PartDefBodyElement::ExhibitState(dummy_node(n, n.value.clone()))
1970        }
1971    };
1972    dummy_node(el, value)
1973}
1974
1975fn normalize_attribute_usage(a: &AttributeUsage) -> AttributeUsage {
1976    AttributeUsage {
1977        name: a.name.clone(),
1978        redefines: a.redefines.clone(),
1979        value: a.value.clone(),
1980        body: a.body.clone(),
1981        name_span: None,
1982        redefines_span: None,
1983    }
1984}
1985
1986fn normalize_part_usage(p: &PartUsage) -> PartUsage {
1987    PartUsage {
1988        is_individual: p.is_individual,
1989        name: p.name.clone(),
1990        type_name: p.type_name.clone(),
1991        multiplicity: p.multiplicity.clone(),
1992        ordered: p.ordered,
1993        subsets: p.subsets.clone(),
1994        redefines: p.redefines.clone(),
1995        value: p.value.clone(),
1996        body: normalize_part_usage_body(&p.body),
1997        name_span: None,
1998        type_ref_span: None,
1999    }
2000}
2001
2002fn normalize_part_usage_body(b: &PartUsageBody) -> PartUsageBody {
2003    match b {
2004        PartUsageBody::Semicolon => PartUsageBody::Semicolon,
2005        PartUsageBody::Brace { elements } => PartUsageBody::Brace {
2006            elements: elements
2007                .iter()
2008                .map(normalize_part_usage_body_element_node)
2009                .collect(),
2010        },
2011    }
2012}
2013
2014fn normalize_perform(p: &Perform) -> Perform {
2015    Perform {
2016        action_name: p.action_name.clone(),
2017        type_name: p.type_name.clone(),
2018        body: normalize_perform_body(&p.body),
2019    }
2020}
2021
2022fn normalize_perform_body(b: &PerformBody) -> PerformBody {
2023    match b {
2024        PerformBody::Semicolon => PerformBody::Semicolon,
2025        PerformBody::Brace { elements } => PerformBody::Brace {
2026            elements: elements
2027                .iter()
2028                .map(normalize_perform_body_element_node)
2029                .collect(),
2030        },
2031    }
2032}
2033
2034fn normalize_perform_body_element_node(el: &Node<PerformBodyElement>) -> Node<PerformBodyElement> {
2035    let value = match &el.value {
2036        PerformBodyElement::Doc(n) => PerformBodyElement::Doc(dummy_node(n, n.value.clone())),
2037        PerformBodyElement::InOut(n) => PerformBodyElement::InOut(dummy_node(
2038            n,
2039            PerformInOutBinding {
2040                direction: n.value.direction,
2041                name: n.value.name.clone(),
2042                value: normalize_expression_node(&n.value.value),
2043            },
2044        )),
2045    };
2046    dummy_node(el, value)
2047}
2048
2049fn normalize_expression_node(node: &Node<Expression>) -> Node<Expression> {
2050    let value = match &node.value {
2051        Expression::LiteralInteger(x) => Expression::LiteralInteger(*x),
2052        Expression::LiteralReal(s) => Expression::LiteralReal(s.clone()),
2053        Expression::LiteralString(s) => Expression::LiteralString(s.clone()),
2054        Expression::LiteralBoolean(b) => Expression::LiteralBoolean(*b),
2055        Expression::FeatureRef(s) => Expression::FeatureRef(s.clone()),
2056        Expression::MemberAccess(base, member) => {
2057            Expression::MemberAccess(Box::new(normalize_expression_node(base)), member.clone())
2058        }
2059        Expression::Index { base, index } => Expression::Index {
2060            base: Box::new(normalize_expression_node(base)),
2061            index: Box::new(normalize_expression_node(index)),
2062        },
2063        Expression::Bracket(inner) => {
2064            Expression::Bracket(Box::new(normalize_expression_node(inner)))
2065        }
2066        Expression::LiteralWithUnit { value: v, unit } => Expression::LiteralWithUnit {
2067            value: Box::new(normalize_expression_node(v)),
2068            unit: Box::new(normalize_expression_node(unit)),
2069        },
2070        Expression::BinaryOp { op, left, right } => Expression::BinaryOp {
2071            op: op.clone(),
2072            left: Box::new(normalize_expression_node(left)),
2073            right: Box::new(normalize_expression_node(right)),
2074        },
2075        Expression::UnaryOp { op, operand } => Expression::UnaryOp {
2076            op: op.clone(),
2077            operand: Box::new(normalize_expression_node(operand)),
2078        },
2079        Expression::Tuple(items) => Expression::Tuple(
2080            items.iter().map(normalize_expression_node).collect(),
2081        ),
2082        Expression::Null => Expression::Null,
2083    };
2084    Node::new(Span::dummy(), value)
2085}
2086
2087fn normalize_part_usage_body_element_node(
2088    el: &Node<PartUsageBodyElement>,
2089) -> Node<PartUsageBodyElement> {
2090    let value = match &el.value {
2091        PartUsageBodyElement::Error(n) => {
2092            PartUsageBodyElement::Error(dummy_node(n, n.value.clone()))
2093        }
2094        PartUsageBodyElement::Doc(n) => PartUsageBodyElement::Doc(dummy_node(n, n.value.clone())),
2095        PartUsageBodyElement::Annotation(n) => {
2096            PartUsageBodyElement::Annotation(dummy_node(n, n.value.clone()))
2097        }
2098        PartUsageBodyElement::AttributeUsage(n) => {
2099            PartUsageBodyElement::AttributeUsage(dummy_node(n, normalize_attribute_usage(&n.value)))
2100        }
2101        PartUsageBodyElement::PartUsage(n) => {
2102            PartUsageBodyElement::PartUsage(Box::new(dummy_node(n, normalize_part_usage(&n.value))))
2103        }
2104        PartUsageBodyElement::OccurrenceUsage(n) => {
2105            PartUsageBodyElement::OccurrenceUsage(Box::new(dummy_node(n, n.value.clone())))
2106        }
2107        PartUsageBodyElement::PortUsage(n) => {
2108            PartUsageBodyElement::PortUsage(dummy_node(n, normalize_port_usage(&n.value)))
2109        }
2110        PartUsageBodyElement::Ref(n) => {
2111            PartUsageBodyElement::Ref(dummy_node(n, normalize_ref_decl(&n.value)))
2112        }
2113        PartUsageBodyElement::Bind(n) => PartUsageBodyElement::Bind(dummy_node(n, n.value.clone())),
2114        PartUsageBodyElement::InterfaceUsage(n) => {
2115            PartUsageBodyElement::InterfaceUsage(dummy_node(n, n.value.clone()))
2116        }
2117        PartUsageBodyElement::Connect(n) => {
2118            PartUsageBodyElement::Connect(dummy_node(n, n.value.clone()))
2119        }
2120        PartUsageBodyElement::Perform(n) => {
2121            PartUsageBodyElement::Perform(dummy_node(n, normalize_perform(&n.value)))
2122        }
2123        PartUsageBodyElement::Allocate(n) => {
2124            PartUsageBodyElement::Allocate(dummy_node(n, n.value.clone()))
2125        }
2126        PartUsageBodyElement::Satisfy(n) => {
2127            PartUsageBodyElement::Satisfy(dummy_node(n, n.value.clone()))
2128        }
2129        PartUsageBodyElement::StateUsage(n) => {
2130            PartUsageBodyElement::StateUsage(dummy_node(n, n.value.clone()))
2131        }
2132        PartUsageBodyElement::MetadataAnnotation(n) => {
2133            PartUsageBodyElement::MetadataAnnotation(dummy_node(n, n.value.clone()))
2134        }
2135    };
2136    dummy_node(el, value)
2137}
2138
2139fn normalize_port_usage(p: &PortUsage) -> PortUsage {
2140    PortUsage {
2141        name: p.name.clone(),
2142        type_name: p.type_name.clone(),
2143        multiplicity: p.multiplicity.clone(),
2144        subsets: p.subsets.clone(),
2145        redefines: p.redefines.clone(),
2146        body: normalize_port_body(&p.body),
2147        name_span: None,
2148        type_ref_span: None,
2149    }
2150}
2151
2152fn normalize_port_body(b: &PortBody) -> PortBody {
2153    match b {
2154        PortBody::Semicolon => PortBody::Semicolon,
2155        PortBody::Brace => PortBody::Brace,
2156        PortBody::BraceWithPorts { elements } => PortBody::BraceWithPorts {
2157            elements: elements
2158                .iter()
2159                .map(|n| dummy_node(n, normalize_port_usage(&n.value)))
2160                .collect(),
2161        },
2162    }
2163}
2164
2165fn normalize_port_def(p: &PortDef) -> PortDef {
2166    PortDef {
2167        identification: p.identification.clone(),
2168        specializes: p.specializes.clone(),
2169        body: normalize_port_def_body(&p.body),
2170    }
2171}
2172
2173fn normalize_port_def_body(b: &PortDefBody) -> PortDefBody {
2174    match b {
2175        PortDefBody::Semicolon => PortDefBody::Semicolon,
2176        PortDefBody::Brace { elements } => PortDefBody::Brace {
2177            elements: elements
2178                .iter()
2179                .map(normalize_port_def_body_element_node)
2180                .collect(),
2181        },
2182    }
2183}
2184
2185fn normalize_port_def_body_element_node(el: &Node<PortDefBodyElement>) -> Node<PortDefBodyElement> {
2186    let value = match &el.value {
2187        PortDefBodyElement::InOutDecl(n) => {
2188            PortDefBodyElement::InOutDecl(dummy_node(n, n.value.clone()))
2189        }
2190        PortDefBodyElement::Doc(n) => PortDefBodyElement::Doc(dummy_node(n, n.value.clone())),
2191        PortDefBodyElement::AttributeDef(n) => {
2192            PortDefBodyElement::AttributeDef(dummy_node(n, normalize_attribute_def(&n.value)))
2193        }
2194        PortDefBodyElement::AttributeUsage(n) => {
2195            PortDefBodyElement::AttributeUsage(dummy_node(n, normalize_attribute_usage(&n.value)))
2196        }
2197        PortDefBodyElement::PortUsage(n) => {
2198            PortDefBodyElement::PortUsage(dummy_node(n, normalize_port_usage(&n.value)))
2199        }
2200    };
2201    dummy_node(el, value)
2202}
2203
2204fn normalize_interface_def(i: &InterfaceDef) -> InterfaceDef {
2205    InterfaceDef {
2206        identification: i.identification.clone(),
2207        body: normalize_interface_def_body(&i.body),
2208    }
2209}
2210
2211fn normalize_connection_def(c: &ConnectionDef) -> ConnectionDef {
2212    ConnectionDef {
2213        annotation: c.annotation.clone(),
2214        identification: c.identification.clone(),
2215        body: normalize_connection_def_body(&c.body),
2216    }
2217}
2218
2219fn normalize_connection_def_body(b: &ConnectionDefBody) -> ConnectionDefBody {
2220    match b {
2221        ConnectionDefBody::Semicolon => ConnectionDefBody::Semicolon,
2222        ConnectionDefBody::Brace { elements } => ConnectionDefBody::Brace {
2223            elements: elements
2224                .iter()
2225                .map(normalize_connection_def_body_element_node)
2226                .collect(),
2227        },
2228    }
2229}
2230
2231fn normalize_connection_def_body_element_node(
2232    el: &Node<ConnectionDefBodyElement>,
2233) -> Node<ConnectionDefBodyElement> {
2234    let value = match &el.value {
2235        ConnectionDefBodyElement::EndDecl(n) => {
2236            ConnectionDefBodyElement::EndDecl(dummy_node(n, normalize_end_decl(&n.value)))
2237        }
2238        ConnectionDefBodyElement::RefDecl(n) => {
2239            ConnectionDefBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2240        }
2241        ConnectionDefBodyElement::ConnectStmt(n) => {
2242            ConnectionDefBodyElement::ConnectStmt(dummy_node(n, n.value.clone()))
2243        }
2244    };
2245    dummy_node(el, value)
2246}
2247
2248fn normalize_metadata_def(m: &MetadataDef) -> MetadataDef {
2249    MetadataDef {
2250        is_abstract: m.is_abstract,
2251        identification: m.identification.clone(),
2252        body: m.body.clone(),
2253    }
2254}
2255
2256fn normalize_enum_def(e: &EnumDef) -> EnumDef {
2257    EnumDef {
2258        identification: e.identification.clone(),
2259        body: e.body.clone(),
2260    }
2261}
2262
2263fn normalize_occurrence_def(o: &OccurrenceDef) -> OccurrenceDef {
2264    OccurrenceDef {
2265        is_abstract: o.is_abstract,
2266        identification: o.identification.clone(),
2267        body: o.body.clone(),
2268    }
2269}
2270
2271fn normalize_interface_def_body(b: &InterfaceDefBody) -> InterfaceDefBody {
2272    match b {
2273        InterfaceDefBody::Semicolon => InterfaceDefBody::Semicolon,
2274        InterfaceDefBody::Brace { elements } => InterfaceDefBody::Brace {
2275            elements: elements
2276                .iter()
2277                .map(normalize_interface_def_body_element_node)
2278                .collect(),
2279        },
2280    }
2281}
2282
2283fn normalize_interface_def_body_element_node(
2284    el: &Node<InterfaceDefBodyElement>,
2285) -> Node<InterfaceDefBodyElement> {
2286    let value = match &el.value {
2287        InterfaceDefBodyElement::Doc(n) => {
2288            InterfaceDefBodyElement::Doc(dummy_node(n, n.value.clone()))
2289        }
2290        InterfaceDefBodyElement::EndDecl(n) => {
2291            InterfaceDefBodyElement::EndDecl(dummy_node(n, normalize_end_decl(&n.value)))
2292        }
2293        InterfaceDefBodyElement::RefDecl(n) => {
2294            InterfaceDefBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2295        }
2296        InterfaceDefBodyElement::ConnectStmt(n) => {
2297            InterfaceDefBodyElement::ConnectStmt(dummy_node(n, n.value.clone()))
2298        }
2299    };
2300    dummy_node(el, value)
2301}
2302
2303fn normalize_end_decl(e: &EndDecl) -> EndDecl {
2304    EndDecl {
2305        name: e.name.clone(),
2306        type_name: e.type_name.clone(),
2307        uses_derived_syntax: e.uses_derived_syntax,
2308        name_span: None,
2309        type_ref_span: None,
2310    }
2311}
2312
2313fn normalize_ref_decl(r: &RefDecl) -> RefDecl {
2314    RefDecl {
2315        name: r.name.clone(),
2316        type_name: r.type_name.clone(),
2317        value: r.value.clone(),
2318        body: r.body.clone(),
2319        name_span: None,
2320        type_ref_span: None,
2321    }
2322}
2323
2324fn normalize_action_def(a: &ActionDef) -> ActionDef {
2325    ActionDef {
2326        identification: a.identification.clone(),
2327        body: normalize_action_def_body(&a.body),
2328    }
2329}
2330
2331fn normalize_action_def_body(b: &ActionDefBody) -> ActionDefBody {
2332    match b {
2333        ActionDefBody::Semicolon => ActionDefBody::Semicolon,
2334        ActionDefBody::Brace { elements } => ActionDefBody::Brace {
2335            elements: elements
2336                .iter()
2337                .map(normalize_action_def_body_element_node)
2338                .collect(),
2339        },
2340    }
2341}
2342
2343fn normalize_action_def_body_element_node(
2344    el: &Node<ActionDefBodyElement>,
2345) -> Node<ActionDefBodyElement> {
2346    let value = match &el.value {
2347        ActionDefBodyElement::Error(n) => {
2348            ActionDefBodyElement::Error(dummy_node(n, n.value.clone()))
2349        }
2350        ActionDefBodyElement::InOutDecl(n) => {
2351            ActionDefBodyElement::InOutDecl(dummy_node(n, n.value.clone()))
2352        }
2353        ActionDefBodyElement::Doc(n) => ActionDefBodyElement::Doc(dummy_node(n, n.value.clone())),
2354        ActionDefBodyElement::Annotation(n) => {
2355            ActionDefBodyElement::Annotation(dummy_node(n, n.value.clone()))
2356        }
2357        ActionDefBodyElement::RefDecl(n) => {
2358            ActionDefBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2359        }
2360        ActionDefBodyElement::Perform(n) => {
2361            ActionDefBodyElement::Perform(dummy_node(n, normalize_perform(&n.value)))
2362        }
2363        ActionDefBodyElement::Bind(n) => ActionDefBodyElement::Bind(dummy_node(n, n.value.clone())),
2364        ActionDefBodyElement::Flow(n) => ActionDefBodyElement::Flow(dummy_node(n, n.value.clone())),
2365        ActionDefBodyElement::FirstStmt(n) => {
2366            ActionDefBodyElement::FirstStmt(dummy_node(n, n.value.clone()))
2367        }
2368        ActionDefBodyElement::MergeStmt(n) => {
2369            ActionDefBodyElement::MergeStmt(dummy_node(n, n.value.clone()))
2370        }
2371        ActionDefBodyElement::StateUsage(n) => {
2372            ActionDefBodyElement::StateUsage(dummy_node(n, n.value.clone()))
2373        }
2374        ActionDefBodyElement::ActionUsage(n) => ActionDefBodyElement::ActionUsage(Box::new(
2375            dummy_node(n, normalize_action_usage(&n.value)),
2376        )),
2377        ActionDefBodyElement::Assign(n) => {
2378            ActionDefBodyElement::Assign(dummy_node(n, n.value.clone()))
2379        }
2380        ActionDefBodyElement::ForLoop(n) => {
2381            ActionDefBodyElement::ForLoop(dummy_node(n, n.value.clone()))
2382        }
2383        ActionDefBodyElement::ThenAction(n) => {
2384            ActionDefBodyElement::ThenAction(dummy_node(n, n.value.clone()))
2385        }
2386        ActionDefBodyElement::Decl(n) => ActionDefBodyElement::Decl(dummy_node(n, n.value.clone())),
2387    };
2388    dummy_node(el, value)
2389}
2390
2391fn normalize_action_usage(a: &ActionUsage) -> ActionUsage {
2392    ActionUsage {
2393        name: a.name.clone(),
2394        type_name: a.type_name.clone(),
2395        accept: a.accept.clone(),
2396        body: normalize_action_usage_body(&a.body),
2397        name_span: None,
2398        type_ref_span: None,
2399    }
2400}
2401
2402fn normalize_action_usage_body(b: &ActionUsageBody) -> ActionUsageBody {
2403    match b {
2404        ActionUsageBody::Semicolon => ActionUsageBody::Semicolon,
2405        ActionUsageBody::Brace { elements } => ActionUsageBody::Brace {
2406            elements: elements
2407                .iter()
2408                .map(normalize_action_usage_body_element_node)
2409                .collect(),
2410        },
2411    }
2412}
2413
2414fn normalize_action_usage_body_element_node(
2415    el: &Node<ActionUsageBodyElement>,
2416) -> Node<ActionUsageBodyElement> {
2417    let value = match &el.value {
2418        ActionUsageBodyElement::Error(n) => {
2419            ActionUsageBodyElement::Error(dummy_node(n, n.value.clone()))
2420        }
2421        ActionUsageBodyElement::Doc(n) => {
2422            ActionUsageBodyElement::Doc(dummy_node(n, n.value.clone()))
2423        }
2424        ActionUsageBodyElement::Annotation(n) => {
2425            ActionUsageBodyElement::Annotation(dummy_node(n, n.value.clone()))
2426        }
2427        ActionUsageBodyElement::InOutDecl(n) => {
2428            ActionUsageBodyElement::InOutDecl(dummy_node(n, n.value.clone()))
2429        }
2430        ActionUsageBodyElement::RefDecl(n) => {
2431            ActionUsageBodyElement::RefDecl(dummy_node(n, normalize_ref_decl(&n.value)))
2432        }
2433        ActionUsageBodyElement::Bind(n) => {
2434            ActionUsageBodyElement::Bind(dummy_node(n, n.value.clone()))
2435        }
2436        ActionUsageBodyElement::Flow(n) => {
2437            ActionUsageBodyElement::Flow(dummy_node(n, n.value.clone()))
2438        }
2439        ActionUsageBodyElement::FirstStmt(n) => {
2440            ActionUsageBodyElement::FirstStmt(dummy_node(n, n.value.clone()))
2441        }
2442        ActionUsageBodyElement::MergeStmt(n) => {
2443            ActionUsageBodyElement::MergeStmt(dummy_node(n, n.value.clone()))
2444        }
2445        ActionUsageBodyElement::StateUsage(n) => {
2446            ActionUsageBodyElement::StateUsage(dummy_node(n, n.value.clone()))
2447        }
2448        ActionUsageBodyElement::ActionUsage(n) => ActionUsageBodyElement::ActionUsage(Box::new(
2449            dummy_node(n, normalize_action_usage(&n.value)),
2450        )),
2451        ActionUsageBodyElement::Assign(n) => {
2452            ActionUsageBodyElement::Assign(dummy_node(n, n.value.clone()))
2453        }
2454        ActionUsageBodyElement::ForLoop(n) => {
2455            ActionUsageBodyElement::ForLoop(dummy_node(n, n.value.clone()))
2456        }
2457        ActionUsageBodyElement::ThenAction(n) => {
2458            ActionUsageBodyElement::ThenAction(dummy_node(n, n.value.clone()))
2459        }
2460        ActionUsageBodyElement::Decl(n) => {
2461            ActionUsageBodyElement::Decl(dummy_node(n, n.value.clone()))
2462        }
2463    };
2464    dummy_node(el, value)
2465}