lex_core/lex/ast/
traits.rs1use super::elements::ContentItem;
7use super::elements::VerbatimLine;
8use super::range::{Position, Range};
9
10pub trait Visitor {
30 fn visit_session(&mut self, _session: &super::Session) {}
32 fn leave_session(&mut self, _session: &super::Session) {}
33
34 fn visit_definition(&mut self, _definition: &super::Definition) {}
35 fn leave_definition(&mut self, _definition: &super::Definition) {}
36
37 fn visit_list(&mut self, _list: &super::List) {}
38 fn leave_list(&mut self, _list: &super::List) {}
39
40 fn visit_list_item(&mut self, _list_item: &super::ListItem) {}
41 fn leave_list_item(&mut self, _list_item: &super::ListItem) {}
42
43 fn visit_paragraph(&mut self, _paragraph: &super::Paragraph) {}
45 fn leave_paragraph(&mut self, _paragraph: &super::Paragraph) {}
46
47 fn visit_text_line(&mut self, _text_line: &super::elements::paragraph::TextLine) {}
48 fn leave_text_line(&mut self, _text_line: &super::elements::paragraph::TextLine) {}
49
50 fn visit_verbatim_block(&mut self, _verbatim_block: &super::Verbatim) {}
51 fn leave_verbatim_block(&mut self, _verbatim_block: &super::Verbatim) {}
52
53 fn visit_table(&mut self, _table: &super::Table) {}
54 fn leave_table(&mut self, _table: &super::Table) {}
55
56 fn visit_verbatim_group(&mut self, _group: &super::elements::verbatim::VerbatimGroupItemRef) {}
57 fn leave_verbatim_group(&mut self, _group: &super::elements::verbatim::VerbatimGroupItemRef) {}
58
59 fn visit_verbatim_line(&mut self, _verbatim_line: &VerbatimLine) {}
60 fn leave_verbatim_line(&mut self, _verbatim_line: &VerbatimLine) {}
61
62 fn visit_annotation(&mut self, _annotation: &super::Annotation) {}
63 fn leave_annotation(&mut self, _annotation: &super::Annotation) {}
64
65 fn visit_blank_line_group(
66 &mut self,
67 _blank_line_group: &super::elements::blank_line_group::BlankLineGroup,
68 ) {
69 }
70 fn leave_blank_line_group(
71 &mut self,
72 _blank_line_group: &super::elements::blank_line_group::BlankLineGroup,
73 ) {
74 }
75}
76
77pub fn visit_children(visitor: &mut dyn Visitor, items: &[ContentItem]) {
79 for item in items {
80 item.accept(visitor);
81 }
82}
83
84pub trait AstNode {
86 fn node_type(&self) -> &'static str;
87 fn display_label(&self) -> String;
88 fn range(&self) -> &Range;
89 fn start_position(&self) -> Position {
90 self.range().start
91 }
92
93 fn accept(&self, visitor: &mut dyn Visitor);
95}
96
97pub trait Container: AstNode {
99 fn label(&self) -> &str;
100 fn children(&self) -> &[ContentItem];
101 fn children_mut(&mut self) -> &mut Vec<ContentItem>;
102}
103
104pub trait VisualStructure: AstNode {
110 fn is_source_line_node(&self) -> bool {
115 false
116 }
117
118 fn has_visual_header(&self) -> bool {
123 false
124 }
125
126 fn collapses_with_children(&self) -> bool {
132 false
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::super::elements::{Paragraph, Session};
139 use super::*;
140
141 #[test]
142 fn test_visitor_traversal() {
143 let para = Paragraph::from_line("Hello, World!".to_string());
145 let session = Session::with_title("Test Session".to_string());
146
147 struct CountingVisitor {
149 session_count: usize,
150 paragraph_count: usize,
151 text_line_count: usize,
152 }
153
154 impl Visitor for CountingVisitor {
155 fn visit_session(&mut self, _: &super::super::Session) {
156 self.session_count += 1;
157 }
158 fn visit_paragraph(&mut self, _: &super::super::Paragraph) {
159 self.paragraph_count += 1;
160 }
161 fn visit_text_line(&mut self, _: &super::super::elements::paragraph::TextLine) {
162 self.text_line_count += 1;
163 }
164 }
165
166 let mut visitor = CountingVisitor {
167 session_count: 0,
168 paragraph_count: 0,
169 text_line_count: 0,
170 };
171
172 para.accept(&mut visitor);
174 assert_eq!(visitor.paragraph_count, 1);
175 assert_eq!(visitor.text_line_count, 1); assert_eq!(visitor.session_count, 0);
177
178 visitor.session_count = 0;
180 visitor.paragraph_count = 0;
181 visitor.text_line_count = 0;
182 session.accept(&mut visitor);
183 assert_eq!(visitor.session_count, 1);
184 assert_eq!(visitor.paragraph_count, 0); }
186}