1pub use crate::ast::AttrList;
7pub use crate::ast::AttrStmt;
8pub use crate::ast::NodeID;
9pub use crate::ast::NodeStmt;
10pub use crate::ast::Port;
11use either::Either;
12use std::collections::HashSet;
13
14pub struct Graph<A> {
16 pub strict: bool,
20 pub is_digraph: bool,
22 pub name: Option<String>,
24 pub stmts: StmtList<A>,
26}
27
28impl<A> Graph<A> {
29 pub fn filter_map<B>(self, f: &dyn Fn(A) -> Option<B>) -> Graph<B> {
37 let new_stmts: StmtList<B> = self.stmts.filter_map_attr(f);
38 Graph {
39 strict: self.strict,
40 is_digraph: self.is_digraph,
41 name: self.name,
42 stmts: new_stmts,
43 }
44 }
45
46 pub fn get_node_ids(&self) -> HashSet<NodeID> {
48 self.stmts.get_node_ids()
49 }
50
51 pub fn get_edges_stmts(self) -> Vec<EdgeStmt<A>> {
54 self.stmts.get_edges_stmts()
55 }
56}
57
58impl<A> From<crate::ast::Graph<A>> for Graph<A>
59where
60 A: Clone,
61{
62 fn from(g: crate::ast::Graph<A>) -> Self {
63 Graph {
64 strict: g.strict,
65 is_digraph: g.is_digraph,
66 name: g.name,
67 stmts: g.stmts.into(),
68 }
69 }
70}
71
72#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
75pub struct StmtList<A> {
76 pub stmts: Vec<Stmt<A>>,
78}
79
80impl<'a, A> StmtList<A> {
81 fn filter_map_attr<B>(self, f: &'a dyn Fn(A) -> Option<B>) -> StmtList<B> {
82 self.stmts
83 .into_iter()
84 .map(|stmt| stmt.filter_map_attr(f))
85 .collect()
86 }
87
88 fn get_node_ids(&self) -> HashSet<NodeID> {
89 let mut hs = HashSet::new();
90 for stmt in self {
91 hs = hs.union(&stmt.get_node_ids()).cloned().collect();
92 }
93 hs
94 }
95
96 fn get_edges_stmts(self) -> Vec<EdgeStmt<A>> {
98 let mut v = Vec::new();
99 for stmt in self {
100 if let Some(edge) = stmt.get_edge() {
101 v.push(edge)
102 }
103 }
104 v
105 }
106}
107
108impl<A> IntoIterator for StmtList<A> {
109 type Item = Stmt<A>;
110 type IntoIter = std::vec::IntoIter<Self::Item>;
111
112 fn into_iter(self) -> Self::IntoIter {
113 self.stmts.into_iter()
114 }
115}
116
117impl<'a, A> IntoIterator for &'a StmtList<A> {
118 type Item = &'a Stmt<A>;
119 type IntoIter = std::slice::Iter<'a, Stmt<A>>;
120
121 fn into_iter(self) -> Self::IntoIter {
122 self.stmts.iter()
123 }
124}
125
126impl<A> FromIterator<Stmt<A>> for StmtList<A> {
127 fn from_iter<T>(iter: T) -> Self
128 where
129 T: IntoIterator<Item = Stmt<A>>,
130 {
131 Self {
132 stmts: iter.into_iter().collect(),
133 }
134 }
135}
136
137impl<A> From<crate::ast::StmtList<A>> for StmtList<A>
138where
139 A: Clone,
140{
141 fn from(stmts: crate::ast::StmtList<A>) -> Self {
142 let mut v = Vec::new();
143 for stmt in stmts {
144 match stmt {
145 crate::ast::Stmt::NodeStmt(n) => {
146 v.push(Stmt::NodeStmt(n));
147 }
148 crate::ast::Stmt::EdgeStmt(e) => {
149 let edges: Vec<EdgeStmt<A>> = e.into();
150 for stmt in edges {
151 v.push(Stmt::EdgeStmt(stmt));
152 }
153 }
154 crate::ast::Stmt::AttrStmt(a) => {
155 v.push(Stmt::AttrStmt(a));
156 }
157 crate::ast::Stmt::IDEq(s1, s2) => {
158 v.push(Stmt::IDEq(s1, s2));
159 }
160 crate::ast::Stmt::Subgraph(graph) => {
161 let stmts: StmtList<A> = graph.stmts.into();
162 for stmt in stmts {
163 v.push(stmt)
164 }
165 }
166 }
167 }
168 Self { stmts: v }
169 }
170}
171
172#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
175pub enum Stmt<A> {
176 NodeStmt(NodeStmt<A>),
178 EdgeStmt(EdgeStmt<A>),
180 AttrStmt(AttrStmt<A>),
182 IDEq(String, String),
184}
185
186impl<'a, A> Stmt<A> {
187 fn filter_map_attr<B>(self, f: &'a dyn Fn(A) -> Option<B>) -> Stmt<B> {
190 match self {
191 Stmt::NodeStmt(node) => Stmt::NodeStmt(node.filter_map_attr(f)),
192 Stmt::EdgeStmt(edge) => Stmt::EdgeStmt(edge.filter_map_attr(f)),
193 Stmt::AttrStmt(attr) => Stmt::AttrStmt(attr.filter_map_attr(f)),
194 Stmt::IDEq(a, b) => Stmt::IDEq(a, b),
195 }
196 }
197
198 pub fn is_node_stmt(&self) -> bool {
200 matches!(self, Stmt::NodeStmt(_))
201 }
202
203 pub fn get_node_ref(&self) -> Option<&NodeStmt<A>> {
206 if let Stmt::NodeStmt(node) = self {
207 Some(node)
208 } else {
209 None
210 }
211 }
212
213 pub fn get_node(self) -> Option<NodeStmt<A>> {
216 if let Stmt::NodeStmt(node) = self {
217 Some(node)
218 } else {
219 None
220 }
221 }
222
223 pub fn is_edge_stmt(&self) -> bool {
225 matches!(self, Stmt::EdgeStmt(_))
226 }
227
228 pub fn get_edge_ref(&self) -> Option<&EdgeStmt<A>> {
231 if let Stmt::EdgeStmt(edge) = self {
232 Some(edge)
233 } else {
234 None
235 }
236 }
237
238 pub fn get_edge(self) -> Option<EdgeStmt<A>> {
241 if let Stmt::EdgeStmt(edge) = self {
242 Some(edge)
243 } else {
244 None
245 }
246 }
247
248 pub fn is_attr_stmt(&self) -> bool {
250 matches!(self, Stmt::AttrStmt(_))
251 }
252
253 pub fn get_attr_ref(&self) -> Option<&AttrStmt<A>> {
256 if let Stmt::AttrStmt(attr) = self {
257 Some(attr)
258 } else {
259 None
260 }
261 }
262
263 pub fn get_attr(self) -> Option<AttrStmt<A>> {
266 if let Stmt::AttrStmt(attr) = self {
267 Some(attr)
268 } else {
269 None
270 }
271 }
272
273 pub fn is_ideq_stmt(&self) -> bool {
275 matches!(self, Stmt::IDEq(..))
276 }
277
278 pub fn get_ideq_ref(&self) -> Option<(&str, &str)> {
281 if let Stmt::IDEq(id1, id2) = self {
282 Some((id1, id2))
283 } else {
284 None
285 }
286 }
287
288 fn get_node_ids(&self) -> HashSet<NodeID> {
290 match self {
291 Stmt::EdgeStmt(e) => e.get_node_ids(),
292 Stmt::NodeStmt(n) => HashSet::from_iter([n.get_node_id().clone()]),
293 _ => HashSet::new(),
294 }
295 }
296}
297
298#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
301pub struct EdgeStmt<A> {
302 pub from: NodeID,
304 pub next: EdgeRHS,
306 pub attr: Option<AttrList<A>>,
308}
309
310impl<A> EdgeStmt<A> {
311 fn filter_map_attr<B>(self, f: &dyn Fn(A) -> Option<B>) -> EdgeStmt<B> {
312 EdgeStmt {
313 from: self.from,
314 next: self.next,
315 attr: self.attr.map(|a| a.filter_map_attr(f)),
316 }
317 }
318
319 fn get_node_ids(&self) -> HashSet<NodeID> {
320 let mut nexts = self.next.get_node_ids();
321 nexts.insert(self.from.clone());
322 nexts
323 }
324}
325
326impl<A> From<crate::ast::EdgeStmt<A>> for Vec<EdgeStmt<A>>
327where
328 A: Clone,
329{
330 fn from(edge: crate::ast::EdgeStmt<A>) -> Vec<EdgeStmt<A>> {
331 let edges = edge.flatten();
332 let mut v: Vec<EdgeStmt<A>> = Vec::new();
333
334 for edge in edges {
335 let from = edge.from;
338 let to = edge.next.to;
339 let attr = edge.attr;
340
341 let (from_ids, mut extra_edges_from) = match from {
342 Either::Left(node_from) => (HashSet::from_iter([node_from]), Vec::new()),
343 Either::Right(subgraph) => {
344 let g: Graph<A> = subgraph.into_graph(false, false).into();
345 (g.get_node_ids(), g.get_edges_stmts())
346 }
347 };
348
349 let (to_ids, mut extra_edges_to) = match to {
350 Either::Left(node_from) => (HashSet::from_iter([node_from]), Vec::new()),
351 Either::Right(subgraph) => {
352 let g: Graph<A> = subgraph.into_graph(false, false).into();
353 (g.get_node_ids(), g.get_edges_stmts())
354 }
355 };
356
357 for from in from_ids {
358 for to in &to_ids {
359 v.push(EdgeStmt {
360 from: from.clone(),
361 next: EdgeRHS {
362 to: to.clone(),
363 next: None,
364 },
365 attr: attr.clone(),
366 });
367 }
368 }
369 v.append(&mut extra_edges_from);
370 v.append(&mut extra_edges_to);
371 }
372 v
373 }
374}
375
376#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
382pub struct EdgeRHS {
383 pub to: NodeID,
385 pub next: Option<Box<EdgeRHS>>,
387}
388
389impl EdgeRHS {
390 fn get_node_ids(&self) -> HashSet<NodeID> {
391 let mut nexts: HashSet<NodeID> = self
392 .next
393 .as_ref()
394 .map(|n| n.get_node_ids())
395 .unwrap_or_default();
396 nexts.insert(self.to.clone());
397 nexts
398 }
399}