1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
6pub struct AstNode {
7 pub node_type: NodeType,
9
10 pub text: String,
12
13 pub children: Vec<AstNode>,
15
16 pub position: Option<Position>,
18
19 pub attributes: HashMap<String, String>,
21
22 pub attribute_keys: Vec<String>,
24}
25
26impl AstNode {
27 pub fn new(node_type: NodeType, text: impl Into<String>) -> Self {
29 Self {
30 node_type,
31 text: text.into(),
32 children: Vec::new(),
33 position: None,
34 attributes: HashMap::new(),
35 attribute_keys: Vec::new(),
36 }
37 }
38
39 pub fn add_child(mut self, child: AstNode) -> Self {
41 self.children.push(child);
42 self
43 }
44
45 pub fn with_position(mut self, position: Position) -> Self {
47 self.position = Some(position);
48 self
49 }
50
51 pub fn with_attribute(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
53 let key = key.into();
54 if !self.attributes.contains_key(&key) {
55 self.attribute_keys.push(key.clone());
56 }
57 self.attributes.insert(key, value.into());
58 self
59 }
60
61 pub fn document() -> Self {
63 Self::new(NodeType::Document, "")
64 }
65
66 pub fn text(text: impl Into<String>) -> Self {
68 Self::new(NodeType::PlainText, text)
69 }
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
74pub struct Position {
75 pub start: usize,
77
78 pub end: usize,
80
81 pub line: usize,
83
84 pub column: usize,
86}
87
88impl Position {
89 pub fn new(start: usize, end: usize, line: usize, column: usize) -> Self {
90 Self {
91 start,
92 end,
93 line,
94 column,
95 }
96 }
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
101pub enum NodeType {
102 Document,
105
106 Paragraph,
108
109 SimpleLine,
111
112 EmptyLine,
114
115 Section,
117
118 PlainText,
121
122 PlainTextSpecialChars,
124
125 PlainTextEmphasis,
127
128 ShortBreak,
131
132 Break,
134
135 ShortEmphasisModerate,
137
138 ShortEmphasisStrong,
140
141 ShortEmphasisNone,
143
144 ShortEmphasisReduced,
146
147 TextModifier,
149
150 ShortIpa,
152
153 BareIpa,
155
156 ShortSub,
158
159 Audio,
161
162 Mark,
164
165 Emphasis,
168
169 Voice,
171
172 Lang,
174
175 Rate,
177
178 Pitch,
180
181 Volume,
183
184 Whisper,
186
187 Excited,
189
190 Disappointed,
192
193 Newscaster,
195
196 Dj,
198
199 Date,
201
202 Time,
204
205 Number,
207
208 Ordinal,
210
211 Characters,
213
214 Fraction,
216
217 Telephone,
219
220 Unit,
222
223 Address,
225
226 Interjection,
228
229 Expletive,
231
232 Ipa,
234
235 Sub,
237}
238
239impl NodeType {
240 pub fn is_emphasis(&self) -> bool {
242 matches!(
243 self,
244 NodeType::ShortEmphasisModerate
245 | NodeType::ShortEmphasisStrong
246 | NodeType::ShortEmphasisNone
247 | NodeType::ShortEmphasisReduced
248 | NodeType::Emphasis
249 )
250 }
251
252 pub fn is_break(&self) -> bool {
254 matches!(self, NodeType::ShortBreak | NodeType::Break)
255 }
256
257 pub fn is_modifier(&self) -> bool {
259 matches!(
260 self,
261 NodeType::Emphasis
262 | NodeType::Voice
263 | NodeType::Lang
264 | NodeType::Rate
265 | NodeType::Pitch
266 | NodeType::Volume
267 | NodeType::Whisper
268 | NodeType::Excited
269 | NodeType::Disappointed
270 | NodeType::Newscaster
271 | NodeType::Dj
272 | NodeType::Date
273 | NodeType::Time
274 | NodeType::Number
275 | NodeType::Ordinal
276 | NodeType::Characters
277 | NodeType::Fraction
278 | NodeType::Telephone
279 | NodeType::Unit
280 | NodeType::Address
281 | NodeType::Interjection
282 | NodeType::Expletive
283 | NodeType::Ipa
284 | NodeType::Sub
285 )
286 }
287}