Skip to main content

sevenmark_parser/ast/
traversable.rs

1use super::{Element, ListContentItem, TableCellItem, TableRowItem};
2
3/// Trait for traversing AST elements
4pub trait Traversable {
5    /// 각 자식 요소에 대해 visitor 호출 (mutable)
6    fn traverse_children<F>(&mut self, visitor: &mut F)
7    where
8        F: FnMut(&mut Element);
9
10    /// 각 자식 요소에 대해 visitor 호출 (immutable)
11    fn traverse_children_ref<F>(&self, visitor: &mut F)
12    where
13        F: FnMut(&Element);
14
15    /// 각 children Vec에 대해 f 호출 (Vec 구조 변경이 필요할 때 사용)
16    fn for_each_children_vec<F>(&mut self, f: &mut F)
17    where
18        F: FnMut(&mut Vec<Element>);
19}
20
21impl Traversable for Element {
22    fn traverse_children<F>(&mut self, visitor: &mut F)
23    where
24        F: FnMut(&mut Element),
25    {
26        match self {
27            // === Leaf nodes (자식 없음) ===
28            Element::Text(_)
29            | Element::Comment(_)
30            | Element::Escape(_)
31            | Element::Error(_)
32            | Element::Code(_)
33            | Element::TeX(_)
34            | Element::Define(_)
35            | Element::ExternalMedia(_)
36            | Element::Null(_)
37            | Element::FootnoteRef(_)
38            | Element::TimeNow(_)
39            | Element::Age(_)
40            | Element::Variable(_)
41            | Element::Mention(_)
42            | Element::SoftBreak(_)
43            | Element::HardBreak(_)
44            | Element::HLine(_) => {}
45
46            // === children 필드만 있는 노드들 ===
47            Element::Literal(e) => e.children.iter_mut().for_each(visitor),
48            Element::Styled(e) => e.children.iter_mut().for_each(visitor),
49            Element::BlockQuote(e) => e.children.iter_mut().for_each(visitor),
50            Element::Ruby(e) => e.children.iter_mut().for_each(visitor),
51            Element::Footnote(e) => e.children.iter_mut().for_each(visitor),
52            Element::Include(e) => e.children.iter_mut().for_each(visitor),
53            Element::Category(e) => e.children.iter_mut().for_each(visitor),
54            Element::Redirect(e) => e.children.iter_mut().for_each(visitor),
55            Element::Media(e) => e.children.iter_mut().for_each(visitor),
56            Element::Bold(e)
57            | Element::Italic(e)
58            | Element::Strikethrough(e)
59            | Element::Underline(e)
60            | Element::Superscript(e)
61            | Element::Subscript(e) => e.children.iter_mut().for_each(visitor),
62            Element::Header(e) => e.children.iter_mut().for_each(visitor),
63
64            // === If: children only (condition은 Expression이므로 순회 안함) ===
65            Element::If(e) => e.children.iter_mut().for_each(visitor),
66
67            // === Table: typed children 순회 ===
68            Element::Table(e) => {
69                for row_item in &mut e.children {
70                    match row_item {
71                        TableRowItem::Row(row) => {
72                            for cell_item in &mut row.children {
73                                match cell_item {
74                                    TableCellItem::Cell(cell) => {
75                                        cell.x.iter_mut().for_each(&mut *visitor);
76                                        cell.y.iter_mut().for_each(&mut *visitor);
77                                        cell.children.iter_mut().for_each(&mut *visitor);
78                                    }
79                                    TableCellItem::Conditional(cond) => {
80                                        for cell in &mut cond.cells {
81                                            cell.x.iter_mut().for_each(&mut *visitor);
82                                            cell.y.iter_mut().for_each(&mut *visitor);
83                                            cell.children.iter_mut().for_each(&mut *visitor);
84                                        }
85                                    }
86                                }
87                            }
88                        }
89                        TableRowItem::Conditional(cond) => {
90                            for row in &mut cond.rows {
91                                for cell_item in &mut row.children {
92                                    match cell_item {
93                                        TableCellItem::Cell(cell) => {
94                                            cell.x.iter_mut().for_each(&mut *visitor);
95                                            cell.y.iter_mut().for_each(&mut *visitor);
96                                            cell.children.iter_mut().for_each(&mut *visitor);
97                                        }
98                                        TableCellItem::Conditional(cond) => {
99                                            for cell in &mut cond.cells {
100                                                cell.x.iter_mut().for_each(&mut *visitor);
101                                                cell.y.iter_mut().for_each(&mut *visitor);
102                                                cell.children.iter_mut().for_each(&mut *visitor);
103                                            }
104                                        }
105                                    }
106                                }
107                            }
108                        }
109                    }
110                }
111            }
112
113            // === List: typed children 순회 ===
114            Element::List(e) => {
115                for item in &mut e.children {
116                    match item {
117                        ListContentItem::Item(li) => {
118                            li.children.iter_mut().for_each(&mut *visitor);
119                        }
120                        ListContentItem::Conditional(cond) => {
121                            for li in &mut cond.items {
122                                li.children.iter_mut().for_each(&mut *visitor);
123                            }
124                        }
125                    }
126                }
127            }
128
129            // === Fold: summary + details ===
130            Element::Fold(e) => {
131                e.summary.children.iter_mut().for_each(&mut *visitor);
132                e.details.children.iter_mut().for_each(&mut *visitor);
133            }
134        }
135    }
136
137    fn traverse_children_ref<F>(&self, visitor: &mut F)
138    where
139        F: FnMut(&Element),
140    {
141        match self {
142            // === Leaf nodes ===
143            Element::Text(_)
144            | Element::Comment(_)
145            | Element::Escape(_)
146            | Element::Error(_)
147            | Element::Code(_)
148            | Element::TeX(_)
149            | Element::Define(_)
150            | Element::ExternalMedia(_)
151            | Element::Null(_)
152            | Element::FootnoteRef(_)
153            | Element::TimeNow(_)
154            | Element::Age(_)
155            | Element::Variable(_)
156            | Element::Mention(_)
157            | Element::SoftBreak(_)
158            | Element::HardBreak(_)
159            | Element::HLine(_) => {}
160
161            Element::Literal(e) => e.children.iter().for_each(visitor),
162            Element::Styled(e) => e.children.iter().for_each(visitor),
163            Element::BlockQuote(e) => e.children.iter().for_each(visitor),
164            Element::Ruby(e) => e.children.iter().for_each(visitor),
165            Element::Footnote(e) => e.children.iter().for_each(visitor),
166            Element::Include(e) => e.children.iter().for_each(visitor),
167            Element::Category(e) => e.children.iter().for_each(visitor),
168            Element::Redirect(e) => e.children.iter().for_each(visitor),
169            Element::Media(e) => e.children.iter().for_each(visitor),
170            Element::Bold(e)
171            | Element::Italic(e)
172            | Element::Strikethrough(e)
173            | Element::Underline(e)
174            | Element::Superscript(e)
175            | Element::Subscript(e) => e.children.iter().for_each(visitor),
176            Element::Header(e) => e.children.iter().for_each(visitor),
177            Element::If(e) => e.children.iter().for_each(visitor),
178
179            Element::Table(e) => {
180                for row_item in &e.children {
181                    match row_item {
182                        TableRowItem::Row(row) => {
183                            for cell_item in &row.children {
184                                match cell_item {
185                                    TableCellItem::Cell(cell) => {
186                                        cell.x.iter().for_each(&mut *visitor);
187                                        cell.y.iter().for_each(&mut *visitor);
188                                        cell.children.iter().for_each(&mut *visitor);
189                                    }
190                                    TableCellItem::Conditional(cond) => {
191                                        for cell in &cond.cells {
192                                            cell.x.iter().for_each(&mut *visitor);
193                                            cell.y.iter().for_each(&mut *visitor);
194                                            cell.children.iter().for_each(&mut *visitor);
195                                        }
196                                    }
197                                }
198                            }
199                        }
200                        TableRowItem::Conditional(cond) => {
201                            for row in &cond.rows {
202                                for cell_item in &row.children {
203                                    match cell_item {
204                                        TableCellItem::Cell(cell) => {
205                                            cell.x.iter().for_each(&mut *visitor);
206                                            cell.y.iter().for_each(&mut *visitor);
207                                            cell.children.iter().for_each(&mut *visitor);
208                                        }
209                                        TableCellItem::Conditional(cond) => {
210                                            for cell in &cond.cells {
211                                                cell.x.iter().for_each(&mut *visitor);
212                                                cell.y.iter().for_each(&mut *visitor);
213                                                cell.children.iter().for_each(&mut *visitor);
214                                            }
215                                        }
216                                    }
217                                }
218                            }
219                        }
220                    }
221                }
222            }
223
224            Element::List(e) => {
225                for item in &e.children {
226                    match item {
227                        ListContentItem::Item(li) => {
228                            li.children.iter().for_each(&mut *visitor);
229                        }
230                        ListContentItem::Conditional(cond) => {
231                            for li in &cond.items {
232                                li.children.iter().for_each(&mut *visitor);
233                            }
234                        }
235                    }
236                }
237            }
238
239            Element::Fold(e) => {
240                e.summary.children.iter().for_each(&mut *visitor);
241                e.details.children.iter().for_each(&mut *visitor);
242            }
243        }
244    }
245
246    fn for_each_children_vec<F>(&mut self, f: &mut F)
247    where
248        F: FnMut(&mut Vec<Element>),
249    {
250        match self {
251            // === Leaf nodes ===
252            Element::Text(_)
253            | Element::Comment(_)
254            | Element::Escape(_)
255            | Element::Error(_)
256            | Element::Code(_)
257            | Element::TeX(_)
258            | Element::Define(_)
259            | Element::ExternalMedia(_)
260            | Element::Null(_)
261            | Element::FootnoteRef(_)
262            | Element::TimeNow(_)
263            | Element::Age(_)
264            | Element::Variable(_)
265            | Element::Mention(_)
266            | Element::SoftBreak(_)
267            | Element::HardBreak(_)
268            | Element::HLine(_)
269            | Element::If(_) => {}
270
271            Element::Literal(e) => f(&mut e.children),
272            Element::Styled(e) => f(&mut e.children),
273            Element::BlockQuote(e) => f(&mut e.children),
274            Element::Ruby(e) => f(&mut e.children),
275            Element::Footnote(e) => f(&mut e.children),
276            Element::Include(e) => f(&mut e.children),
277            Element::Category(e) => f(&mut e.children),
278            Element::Redirect(e) => f(&mut e.children),
279            Element::Media(e) => f(&mut e.children),
280            Element::Bold(e)
281            | Element::Italic(e)
282            | Element::Strikethrough(e)
283            | Element::Underline(e)
284            | Element::Superscript(e)
285            | Element::Subscript(e) => f(&mut e.children),
286            Element::Header(e) => f(&mut e.children),
287
288            Element::Table(e) => {
289                for row_item in &mut e.children {
290                    match row_item {
291                        TableRowItem::Row(row) => {
292                            for cell_item in &mut row.children {
293                                match cell_item {
294                                    TableCellItem::Cell(cell) => {
295                                        f(&mut cell.x);
296                                        f(&mut cell.y);
297                                        f(&mut cell.children);
298                                    }
299                                    TableCellItem::Conditional(cond) => {
300                                        for cell in &mut cond.cells {
301                                            f(&mut cell.x);
302                                            f(&mut cell.y);
303                                            f(&mut cell.children);
304                                        }
305                                    }
306                                }
307                            }
308                        }
309                        TableRowItem::Conditional(cond) => {
310                            for row in &mut cond.rows {
311                                for cell_item in &mut row.children {
312                                    match cell_item {
313                                        TableCellItem::Cell(cell) => {
314                                            f(&mut cell.x);
315                                            f(&mut cell.y);
316                                            f(&mut cell.children);
317                                        }
318                                        TableCellItem::Conditional(cond) => {
319                                            for cell in &mut cond.cells {
320                                                f(&mut cell.x);
321                                                f(&mut cell.y);
322                                                f(&mut cell.children);
323                                            }
324                                        }
325                                    }
326                                }
327                            }
328                        }
329                    }
330                }
331            }
332
333            Element::List(e) => {
334                for item in &mut e.children {
335                    match item {
336                        ListContentItem::Item(li) => f(&mut li.children),
337                        ListContentItem::Conditional(cond) => {
338                            for li in &mut cond.items {
339                                f(&mut li.children);
340                            }
341                        }
342                    }
343                }
344            }
345
346            Element::Fold(e) => {
347                f(&mut e.summary.children);
348                f(&mut e.details.children);
349            }
350        }
351    }
352}