1use std::collections::HashMap;
2
3use crate::source_location::SourceLocation;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum Mode {
8
9 Math,
10 Text,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum AtomFamily {
16
17 Mord,
18 Mop,
19 Mbin,
20 Mrel,
21 Mopen,
22 Mclose,
23 Mpunct,
24 Minner,
25}
26
27#[derive(Debug, Clone, PartialEq)]
28pub struct Measurement {
30 pub number: f64,
31 pub unit: String,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum StyleLevel {
37
38 DisplayStyle,
39 TextStyle,
40 ScriptStyle,
41 ScriptScriptStyle,
42}
43
44#[derive(Debug, Clone, PartialEq)]
45pub enum OperatorContent {
47 SymbolOperator(String),
48 BodyOperator(Vec<ParseNode>),
49 NamedOperator(String),
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53pub enum LapAlignment {
55
56 LLap,
57 RLap,
58 CLap,
59}
60
61#[derive(Debug, Clone, PartialEq)]
62pub enum ArrayColumn {
64 AlignColumn {
65 alignment: String,
66 pre_gap: f64,
67 post_gap: f64,
68 },
69 SeparatorColumn {
70 separator: String,
71 },
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum ColumnSeparationType {
77
78 AlignSeparation,
79 AlignAtSeparation,
80 GatherSeparation,
81 SmallSeparation,
82 CdSeparation,
83}
84
85#[derive(Debug, Clone, PartialEq)]
86pub enum ParseNode {
88 Internal { mode: Mode },
89 Raw { mode: Mode, string: String },
90 ColorToken { mode: Mode, color: String },
91 Size {
92 mode: Mode,
93 value: Measurement,
94 is_blank: bool,
95 },
96 Url { mode: Mode, url: String },
97 Styling {
98 mode: Mode,
99 body: Vec<ParseNode>,
100 style: StyleLevel,
101 reset_font: bool,
102 },
103 Sqrt {
104 mode: Mode,
105 body: Box<ParseNode>,
106 index: Option<Box<ParseNode>>,
107 },
108 Infix {
109 mode: Mode,
110 replace_with: String,
111 size: Option<Measurement>,
112 loc: Option<SourceLocation>,
113 },
114 GenFrac {
115 mode: Mode,
116 numer: Box<ParseNode>,
117 denom: Box<ParseNode>,
118 continued: bool,
119 has_bar_line: bool,
120 bar_size: Option<Measurement>,
121 left_delim: Option<String>,
122 right_delim: Option<String>,
123 },
124 Text {
125 mode: Mode,
126 body: Vec<ParseNode>,
127 font: String,
128 },
129 Font {
130 mode: Mode,
131 font: String,
132 body: Box<ParseNode>,
133 },
134 MClass {
135 mode: Mode,
136 mclass: AtomFamily,
137 body: Vec<ParseNode>,
138 is_character_box: bool,
139 },
140 Op {
141 mode: Mode,
142 limits: bool,
143 always_handle_sup_sub: bool,
144 parent_is_sup_sub: bool,
145 suppress_base_shift: bool,
146 content: OperatorContent,
147 },
148 OperatorName {
149 mode: Mode,
150 body: Vec<ParseNode>,
151 always_handle_sup_sub: bool,
152 limits: bool,
153 parent_is_sup_sub: bool,
154 },
155 Overline { mode: Mode, body: Box<ParseNode> },
156 Underline { mode: Mode, body: Box<ParseNode> },
157 Smash {
158 mode: Mode,
159 body: Box<ParseNode>,
160 smash_height: bool,
161 smash_depth: bool,
162 },
163 Phantom { mode: Mode, body: Vec<ParseNode> },
164 VPhantom { mode: Mode, body: Box<ParseNode> },
165 Pmb {
166 mode: Mode,
167 mclass: AtomFamily,
168 body: Vec<ParseNode>,
169 },
170 VCenter { mode: Mode, body: Box<ParseNode> },
171 Rule {
172 mode: Mode,
173 shift: Option<Measurement>,
174 width: Measurement,
175 height: Measurement,
176 },
177 RaiseBox {
178 mode: Mode,
179 dy: Measurement,
180 body: Box<ParseNode>,
181 },
182 HBox { mode: Mode, body: Vec<ParseNode> },
183 Lap {
184 mode: Mode,
185 alignment: LapAlignment,
186 body: Box<ParseNode>,
187 },
188 MathChoice {
189 mode: Mode,
190 display: Vec<ParseNode>,
191 text: Vec<ParseNode>,
192 script: Vec<ParseNode>,
193 scriptscript: Vec<ParseNode>,
194 },
195 Sizing {
196 mode: Mode,
197 size: usize,
198 body: Vec<ParseNode>,
199 },
200 HorizBrace {
201 mode: Mode,
202 label: String,
203 is_over: bool,
204 base: Box<ParseNode>,
205 },
206 XArrow {
207 mode: Mode,
208 label: String,
209 body: Box<ParseNode>,
210 below: Option<Box<ParseNode>>,
211 },
212 AccentUnder {
213 mode: Mode,
214 label: String,
215 base: Box<ParseNode>,
216 },
217 DelimSizing {
218 mode: Mode,
219 size: usize,
220 mclass: AtomFamily,
221 delim: String,
222 },
223 LeftRightRight {
224 mode: Mode,
225 delim: String,
226 color: Option<String>,
227 },
228 LeftRight {
229 mode: Mode,
230 body: Vec<ParseNode>,
231 left: String,
232 right: String,
233 right_color: Option<String>,
234 },
235 Middle { mode: Mode, delim: String },
236 Kern { mode: Mode, dimension: Measurement },
237 Enclose {
238 mode: Mode,
239 body: Box<ParseNode>,
240 label: String,
241 background_color: Option<String>,
242 border_color: Option<String>,
243 },
244 Href {
245 mode: Mode,
246 href: String,
247 body: Vec<ParseNode>,
248 },
249 Html {
250 mode: Mode,
251 attributes: HashMap<String, String>,
252 body: Vec<ParseNode>,
253 },
254 IncludeGraphics {
255 mode: Mode,
256 alt: String,
257 width: Measurement,
258 height: Measurement,
259 totalheight: Measurement,
260 src: String,
261 },
262 Tag {
263 mode: Mode,
264 body: Vec<ParseNode>,
265 tag: Vec<ParseNode>,
266 },
267 Array {
268 mode: Mode,
269 body: Vec<Vec<ParseNode>>,
270 add_jot: bool,
271 array_stretch: f64,
272 columns: Option<Vec<ArrayColumn>>,
273 row_gaps: Vec<Option<Measurement>>,
274 hskip_before_and_after: bool,
275 hlines_before_row: Vec<Vec<bool>>,
276 column_separation_type: Option<ColumnSeparationType>,
277 tags: Option<Vec<Option<Vec<ParseNode>>>>,
278 auto_tags: Option<Vec<bool>>,
279 leqno: bool,
280 },
281 EnvironmentEnd { mode: Mode, name: String },
282 CdLabel {
283 mode: Mode,
284 side: String,
285 label: Box<ParseNode>,
286 },
287 CdParent {
288 mode: Mode,
289 fragment: Box<ParseNode>,
290 },
291 Cr {
292 mode: Mode,
293 new_line: bool,
294 size: Option<Measurement>,
295 },
296 HtmlMathML {
297 mode: Mode,
298 html: Vec<ParseNode>,
299 mathml: Vec<ParseNode>,
300 },
301 OrdGroup {
302 mode: Mode,
303 loc: Option<SourceLocation>,
304 body: Vec<ParseNode>,
305 semisimple: bool,
306 },
307 SupSub {
308 mode: Mode,
309 base: Option<Box<ParseNode>>,
310 sup: Option<Box<ParseNode>>,
311 sub: Option<Box<ParseNode>>,
312 },
313 TextOrd {
314 mode: Mode,
315 loc: Option<SourceLocation>,
316 text: String,
317 },
318 MathOrd {
319 mode: Mode,
320 loc: Option<SourceLocation>,
321 text: String,
322 },
323 Spacing {
324 mode: Mode,
325 loc: Option<SourceLocation>,
326 text: String,
327 },
328 AccentToken {
329 mode: Mode,
330 loc: Option<SourceLocation>,
331 text: String,
332 },
333 OperatorToken {
334 mode: Mode,
335 loc: Option<SourceLocation>,
336 text: String,
337 },
338 Accent {
339 mode: Mode,
340 loc: Option<SourceLocation>,
341 label: String,
342 is_stretchy: bool,
343 is_shifty: bool,
344 base: Box<ParseNode>,
345 },
346 Verb {
347 mode: Mode,
348 loc: Option<SourceLocation>,
349 body: String,
350 star: bool,
351 },
352 Atom {
353 mode: Mode,
354 loc: Option<SourceLocation>,
355 family: AtomFamily,
356 text: String,
357 },
358 Color {
359 mode: Mode,
360 color: String,
361 body: Vec<ParseNode>,
362 },
363}
364
365impl ParseNode {
366 pub fn mode(&self) -> Mode {
368 match self {
369 ParseNode::Internal { mode }
370 | ParseNode::Raw { mode, .. }
371 | ParseNode::ColorToken { mode, .. }
372 | ParseNode::Size { mode, .. }
373 | ParseNode::Url { mode, .. }
374 | ParseNode::Styling { mode, .. }
375 | ParseNode::Sqrt { mode, .. }
376 | ParseNode::Infix { mode, .. }
377 | ParseNode::GenFrac { mode, .. }
378 | ParseNode::Text { mode, .. }
379 | ParseNode::Font { mode, .. }
380 | ParseNode::MClass { mode, .. }
381 | ParseNode::Op { mode, .. }
382 | ParseNode::OperatorName { mode, .. }
383 | ParseNode::Overline { mode, .. }
384 | ParseNode::Underline { mode, .. }
385 | ParseNode::Smash { mode, .. }
386 | ParseNode::Phantom { mode, .. }
387 | ParseNode::VPhantom { mode, .. }
388 | ParseNode::Pmb { mode, .. }
389 | ParseNode::VCenter { mode, .. }
390 | ParseNode::Rule { mode, .. }
391 | ParseNode::RaiseBox { mode, .. }
392 | ParseNode::HBox { mode, .. }
393 | ParseNode::Lap { mode, .. }
394 | ParseNode::MathChoice { mode, .. }
395 | ParseNode::Sizing { mode, .. }
396 | ParseNode::HorizBrace { mode, .. }
397 | ParseNode::XArrow { mode, .. }
398 | ParseNode::AccentUnder { mode, .. }
399 | ParseNode::DelimSizing { mode, .. }
400 | ParseNode::LeftRightRight { mode, .. }
401 | ParseNode::LeftRight { mode, .. }
402 | ParseNode::Middle { mode, .. }
403 | ParseNode::Kern { mode, .. }
404 | ParseNode::Enclose { mode, .. }
405 | ParseNode::Href { mode, .. }
406 | ParseNode::Html { mode, .. }
407 | ParseNode::IncludeGraphics { mode, .. }
408 | ParseNode::Tag { mode, .. }
409 | ParseNode::Array { mode, .. }
410 | ParseNode::EnvironmentEnd { mode, .. }
411 | ParseNode::CdLabel { mode, .. }
412 | ParseNode::CdParent { mode, .. }
413 | ParseNode::Cr { mode, .. }
414 | ParseNode::HtmlMathML { mode, .. }
415 | ParseNode::OrdGroup { mode, .. }
416 | ParseNode::SupSub { mode, .. }
417 | ParseNode::TextOrd { mode, .. }
418 | ParseNode::MathOrd { mode, .. }
419 | ParseNode::Spacing { mode, .. }
420 | ParseNode::AccentToken { mode, .. }
421 | ParseNode::OperatorToken { mode, .. }
422 | ParseNode::Accent { mode, .. }
423 | ParseNode::Verb { mode, .. }
424 | ParseNode::Atom { mode, .. }
425 | ParseNode::Color { mode, .. } => *mode,
426 }
427 }
428}