Skip to main content

sysml_v2_parser/ast/
behavior.rs

1use super::common::{ConnectBody, DocComment, Identification, ParseErrorNode};
2use super::requirement::RequirementUsage;
3use super::structure::{
4    Annotation, Bind, DefinitionBody, MetadataAnnotation, MetadataKeywordUsage, Perform, RefDecl,
5};
6use crate::ast::core::{Expression, Node, Span};
7
8/// Action definition: `action def` Identification body (in/out params).
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct ActionDef {
11    pub identification: Identification,
12    pub specializes: Option<String>,
13    pub specializes_span: Option<Span>,
14    pub body: ActionDefBody,
15}
16
17/// Body of an action definition: `;` or `{` ActionDefBodyElement* `}`.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum ActionDefBody {
20    Semicolon,
21    Brace {
22        elements: Vec<Node<ActionDefBodyElement>>,
23    },
24}
25
26/// Element inside an action definition body.
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum ActionDefBodyElement {
29    Error(Node<ParseErrorNode>),
30    InOutDecl(Node<InOutDecl>),
31    Doc(Node<DocComment>),
32    Annotation(Node<Annotation>),
33    MetadataAnnotation(Node<MetadataAnnotation>),
34    RefDecl(Node<RefDecl>),
35    Perform(Node<Perform>),
36    Bind(Node<Bind>),
37    Flow(Node<Flow>),
38    FirstStmt(Node<FirstStmt>),
39    MergeStmt(Node<MergeStmt>),
40    StateUsage(Node<StateUsage>),
41    ActionUsage(Box<Node<ActionUsage>>),
42    Assign(Node<AssignStmt>),
43    ForLoop(Node<ForLoop>),
44    ThenAction(Node<ThenAction>),
45    Decl(Node<ActionBodyDecl>),
46}
47
48/// Assignment statement (SysML v2 AssignmentNode/AssignmentActionUsage).
49///
50/// Examples:
51/// - `assign x := y;`
52/// - `then assign position := dynamics.x_out;`
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct AssignStmt {
55    pub is_then: bool,
56    pub lhs: String,
57    pub rhs: String,
58}
59
60/// For-loop node (SysML v2 ForLoopNode) - modeled minimally.
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct ForLoop {
63    pub var: String,
64    pub range: String,
65    pub body: ActionDefBody,
66}
67
68/// Succession to an action usage: `then action ...`.
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct ThenAction {
71    pub action: Node<ActionUsage>,
72}
73
74/// In/out parameter in action def: `in` name `:` type `;` or `out` name `:` type `;`.
75#[derive(Debug, Clone, PartialEq, Eq)]
76pub struct InOutDecl {
77    pub direction: InOut,
78    pub name: String,
79    pub type_name: String,
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83pub enum InOut {
84    In,
85    Out,
86    InOut,
87}
88
89/// Typed payload on accept/send control nodes: `accept name : Type` or `send name : Type`.
90#[derive(Debug, Clone, PartialEq, Eq)]
91pub struct PayloadClause {
92    pub name: String,
93    pub type_name: Option<String>,
94    pub name_span: Span,
95    pub type_span: Option<Span>,
96}
97
98/// Transition accept trigger: typed payload or shorthand expression (`accept StartPressed`).
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub enum TransitionAccept {
101    Payload(PayloadClause),
102    Shorthand(Node<Expression>),
103}
104
105/// Action usage: `action` name `:` type_name (`accept` param_name `:` param_type)? body.
106#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct ActionUsage {
108    pub name: String,
109    pub type_name: String,
110    /// For `action ... accept param : Type` form.
111    pub accept: Option<PayloadClause>,
112    /// For standalone `send param : Type` control-node statements.
113    pub send: Option<PayloadClause>,
114    pub body: ActionUsageBody,
115    /// Span of the usage name (for semantic tokens).
116    pub name_span: Option<Span>,
117    /// Span of the type reference after `:` (for semantic tokens).
118    pub type_ref_span: Option<Span>,
119}
120
121/// Body of an action usage: `;` or `{` ActionUsageBodyElement* `}`.
122#[derive(Debug, Clone, PartialEq, Eq)]
123pub enum ActionUsageBody {
124    Semicolon,
125    Brace {
126        elements: Vec<Node<ActionUsageBodyElement>>,
127    },
128}
129
130/// Element inside an action usage body.
131#[derive(Debug, Clone, PartialEq, Eq)]
132pub enum ActionUsageBodyElement {
133    Error(Node<ParseErrorNode>),
134    Doc(Node<DocComment>),
135    Annotation(Node<Annotation>),
136    MetadataAnnotation(Node<MetadataAnnotation>),
137    InOutDecl(Node<InOutDecl>),
138    RefDecl(Node<RefDecl>),
139    Bind(Node<Bind>),
140    Flow(Node<Flow>),
141    FirstStmt(Node<FirstStmt>),
142    MergeStmt(Node<MergeStmt>),
143    StateUsage(Node<StateUsage>),
144    ActionUsage(Box<Node<ActionUsage>>),
145    Assign(Node<AssignStmt>),
146    ForLoop(Node<ForLoop>),
147    ThenAction(Node<ThenAction>),
148    Decl(Node<ActionBodyDecl>),
149}
150
151/// A minimally-modeled declaration inside an action/behavior body (e.g. `attribute ...;`, `calc ...;`).
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub struct ActionBodyDecl {
154    pub keyword: String,
155    pub text: String,
156}
157
158/// Flow: `flow` from `to` to body.
159#[derive(Debug, Clone, PartialEq, Eq)]
160pub struct Flow {
161    pub from: Node<Expression>,
162    pub to: Node<Expression>,
163    pub body: ConnectBody,
164}
165
166/// Flow definition: `flow def` Identification body.
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub struct FlowDef {
169    pub identification: Identification,
170    pub specializes: Option<String>,
171    pub specializes_span: Option<Span>,
172    pub body: DefinitionBody,
173}
174
175/// Flow usage: `flow` name (`:` type)? [`from` expr `to` expr]? body.
176#[derive(Debug, Clone, PartialEq, Eq)]
177pub struct FlowUsage {
178    pub name: String,
179    pub type_name: Option<String>,
180    pub from: Option<Node<Expression>>,
181    pub to: Option<Node<Expression>>,
182    pub body: DefinitionBody,
183}
184
185/// First/then control flow: `first` expr `then` expr body.
186#[derive(Debug, Clone, PartialEq, Eq)]
187pub struct FirstStmt {
188    pub first: Node<Expression>,
189    pub then: Node<Expression>,
190    pub body: FirstMergeBody,
191}
192
193/// Merge: `merge` expr body.
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct MergeStmt {
196    pub merge: Node<Expression>,
197    pub body: FirstMergeBody,
198}
199
200/// Body of first/merge: `;` or `{` ... `}`.
201#[derive(Debug, Clone, PartialEq, Eq)]
202pub enum FirstMergeBody {
203    Semicolon,
204    Brace,
205}
206
207// ---------------------------------------------------------------------------
208// Allocation
209// ---------------------------------------------------------------------------
210
211/// Allocate statement at part usage level: `allocate` from `to` to body.
212#[derive(Debug, Clone, PartialEq, Eq)]
213pub struct Allocate {
214    pub source: Node<Expression>,
215    pub target: Node<Expression>,
216    pub body: ConnectBody,
217}
218
219/// Allocation definition: `allocation def` Identification body.
220#[derive(Debug, Clone, PartialEq, Eq)]
221pub struct AllocationDef {
222    pub identification: Identification,
223    pub specializes: Option<String>,
224    pub specializes_span: Option<Span>,
225    pub body: DefinitionBody,
226}
227
228/// Allocation usage: `allocation` name (`:` type)? [`allocate` source `to` target]? body.
229#[derive(Debug, Clone, PartialEq, Eq)]
230pub struct AllocationUsage {
231    pub name: String,
232    pub type_name: Option<String>,
233    pub source: Option<Node<Expression>>,
234    pub target: Option<Node<Expression>>,
235    pub body: DefinitionBody,
236}
237
238// ---------------------------------------------------------------------------
239// Requirements
240// ---------------------------------------------------------------------------
241
242/// State definition: `state def` Identification body.
243#[derive(Debug, Clone, PartialEq, Eq)]
244pub struct StateDef {
245    pub identification: Identification,
246    pub specializes: Option<String>,
247    pub specializes_span: Option<Span>,
248    pub body: StateDefBody,
249}
250
251#[derive(Debug, Clone, PartialEq, Eq)]
252pub enum StateDefBody {
253    Semicolon,
254    Brace {
255        elements: Vec<Node<StateDefBodyElement>>,
256    },
257}
258
259#[derive(Debug, Clone, PartialEq, Eq)]
260pub enum StateDefBodyElement {
261    Error(Node<ParseErrorNode>),
262    Doc(Node<DocComment>),
263    Annotation(Node<Annotation>),
264    MetadataKeywordUsage(Node<MetadataKeywordUsage>),
265    Other(String),
266    /// `entry` (`;` or body) - entry action.
267    Entry(Node<EntryAction>),
268    /// `then` name `;` - initial state.
269    Then(Node<ThenStmt>),
270    /// `final` / `final state` name `;` - explicit final state.
271    FinalState(Node<FinalState>),
272    /// `ref` name `:` type body ÔÇô reference binding in state.
273    Ref(Node<RefDecl>),
274    RequirementUsage(Node<RequirementUsage>),
275    StateUsage(Node<StateUsage>),
276    Transition(Node<Transition>),
277}
278
279/// Entry action: `entry` (`;` or body).
280#[derive(Debug, Clone, PartialEq, Eq)]
281pub struct EntryAction {
282    /// For `entry action name body` form; None for plain `entry` body.
283    pub action_name: Option<String>,
284    pub body: StateDefBody,
285}
286
287/// Then (initial state): `then` name `;`
288#[derive(Debug, Clone, PartialEq, Eq)]
289pub struct ThenStmt {
290    pub state_name: String,
291    pub name_span: Option<Span>,
292}
293
294/// Final state: `final` name `;` or `final state` name `;`
295#[derive(Debug, Clone, PartialEq, Eq)]
296pub struct FinalState {
297    pub state_name: String,
298    pub name_span: Span,
299}
300
301/// State usage: `state` name (`:` type)? body.
302#[derive(Debug, Clone, PartialEq, Eq)]
303pub struct StateUsage {
304    pub name: String,
305    pub type_name: Option<String>,
306    pub body: StateDefBody,
307}
308
309/// Transition: `transition` name [`first` source [`accept` trigger]] [`if` guard] [`do` effect] `then` target body.
310#[derive(Debug, Clone, PartialEq, Eq)]
311pub struct Transition {
312    pub name: Option<String>,
313    /// If omitted, form is `transition name then target;`.
314    pub source: Option<Node<Expression>>,
315    /// When `first` is present on a transition, the source state is also an initial state.
316    pub is_initial: bool,
317    /// Structured or shorthand accept trigger after `first` source.
318    pub accept: Option<TransitionAccept>,
319    pub guard: Option<Node<Expression>>,
320    pub effect: Option<Node<Expression>>,
321    pub target: Node<Expression>,
322    pub body: ConnectBody,
323}
324
325// ---------------------------------------------------------------------------
326// Constraints & Calculations
327// ---------------------------------------------------------------------------