1use crate::tree::{
2 Expression, Frac, Func, Group, Intermediate, Matrix, Script, ScriptFunc, Simple, SimpleBinary,
3 SimpleFunc, SimpleScript, SimpleUnary,
4};
5use crate::{Token, Tokenizer};
6
7const MAX_DEPTH: usize = 256;
12
13struct Entry<'a> {
15 text: &'a str,
16 token: Token,
17 close: usize,
19 has_sep: bool,
21}
22
23struct Parser<'a> {
28 entries: Box<[Entry<'a>]>,
29 pos: usize,
30 depth: usize,
32}
33
34impl<'a> Parser<'a> {
35 fn new(tokens: impl IntoIterator<Item = (&'a str, Token)>) -> Self {
36 let mut entries: Vec<Entry<'a>> = tokens
38 .into_iter()
39 .map(|(text, token)| Entry {
40 text,
41 token,
42 close: usize::MAX,
43 has_sep: false,
44 })
45 .collect();
46 let mut open_stack: Vec<usize> = Vec::new();
48 for index in 0..entries.len() {
49 match entries[index].token {
50 Token::OpenBracket => open_stack.push(index),
51 Token::CloseBracket => {
52 if let Some(open) = open_stack.pop() {
53 entries[open].close = index;
54 }
55 }
56 Token::Sep => {
57 if let Some(&open) = open_stack.last() {
58 entries[open].has_sep = true;
59 }
60 }
61 _ => {}
62 }
63 }
64 Parser {
65 entries: entries.into(),
66 pos: 0,
67 depth: 0,
68 }
69 }
70
71 fn advance(&mut self) -> Option<(&'a str, Token)> {
73 let item = self
74 .entries
75 .get(self.pos)
76 .map(|entry| (entry.text, entry.token));
77 if item.is_some() {
78 self.pos += 1;
79 }
80 item
81 }
82
83 fn next_simple(&mut self, stop: Option<Token>) -> Option<Simple<'a>> {
84 if self.depth >= MAX_DEPTH {
85 return None;
86 }
87 self.depth += 1;
88 let mark = self.pos;
89 let result = match self.advance() {
90 Some((_, token)) if Some(token) == stop => {
91 self.pos = mark; None
93 }
94 Some((num, Token::Number)) => Some(Simple::Number(num)),
95 Some((text, Token::Text)) => Some(Simple::Text(text)),
96 Some((ident, Token::Ident)) => Some(Simple::Ident(ident)),
97 Some((symb, Token::Symbol)) => Some(Simple::Symbol(symb)),
98 Some((unary, Token::Unary)) => {
99 Some(SimpleUnary::new(unary, self.next_simple(None).unwrap_or_default()).into())
100 }
101 Some((func, Token::Function)) => {
102 Some(SimpleFunc::new(func, self.next_simple(None).unwrap_or_default()).into())
103 }
104 Some((binary, Token::Binary)) => Some(
105 SimpleBinary::new(
106 binary,
107 self.next_simple(None).unwrap_or_default(),
108 self.next_simple(None).unwrap_or_default(),
109 )
110 .into(),
111 ),
112 Some((_, Token::CloseBracket)) => {
113 self.pos = mark; None
115 }
116 Some((open, Token::OpenBracket)) => Some({
117 let matrix = self.could_be_matrix().then(|| {
119 let mark = self.pos;
120 self.next_matrix(open).or_else(|| {
121 self.pos = mark; None
123 })
124 });
125 match matrix {
126 Some(Some(matrix)) => matrix.into(),
127 _ => self.next_open_group(open).into(),
128 }
129 }),
130 Some((open, Token::OpenCloseBracket)) => Some(self.next_open_close_group(open)),
131 Some((raw, Token::Frac | Token::Super | Token::Sub | Token::Sep)) => {
132 Some(Simple::Symbol(raw))
133 }
134 None => None,
135 };
136 self.depth -= 1;
137 result
138 }
139
140 fn could_be_matrix(&self) -> bool {
145 let outer_open = self.pos - 1;
146 let row_open = self.pos;
147 if !self
149 .entries
150 .get(row_open)
151 .is_some_and(|entry| entry.token == Token::OpenBracket)
152 {
153 return false;
154 }
155 let row_close = self.entries[row_open].close;
156 if row_close >= self.entries.len() {
157 return false; }
159 let after = row_close + 1;
160 if self
161 .entries
162 .get(after)
163 .is_some_and(|entry| entry.token == Token::Sep)
164 {
165 true } else if after == self.entries[outer_open].close {
167 self.entries[row_open].has_sep } else {
169 false
170 }
171 }
172
173 fn next_open_group(&mut self, open: &'a str) -> Group<'a> {
174 let expr = self.next_expression(None);
175 let mark = self.pos;
176 let close = if let Some((bracket, Token::CloseBracket)) = self.advance() {
177 bracket
178 } else {
179 self.pos = mark; ""
182 };
183 Group::new(open, expr, close)
184 }
185
186 fn next_open_close_group(&mut self, open: &'a str) -> Simple<'a> {
187 let mark = self.pos;
188 if let Some(first) = self.next_intermediate(None) {
189 let mut inters = vec![first];
191 while let Some(inter) = self.next_intermediate(Some(Token::OpenCloseBracket)) {
192 inters.push(inter);
193 }
194 if let Some((close, Token::OpenCloseBracket)) = self.advance() {
195 Simple::Group(Group::new(open, inters, close))
196 } else {
197 self.pos = mark; Simple::Symbol(open)
200 }
201 } else {
202 Simple::Symbol(open)
204 }
205 }
206
207 fn next_expression(&mut self, stop: Option<Token>) -> Expression<'a> {
208 let mut inters = Vec::new();
209 while let Some(inter) = self.next_intermediate(stop) {
210 inters.push(inter);
211 }
212 inters.into()
213 }
214
215 fn next_matrix_row(
216 &mut self,
217 exprs: &mut impl Extend<Expression<'a>>,
218 ) -> Option<(&'a str, usize, &'a str)> {
219 let open = match self.advance() {
220 Some((open, Token::OpenBracket)) => Some(open),
221 _ => None,
222 }?;
223 let mut len = 1;
224 exprs.extend([self.next_expression(Some(Token::Sep))]);
225 loop {
226 match self.advance() {
227 Some((_, Token::Sep)) => {
228 exprs.extend([self.next_expression(Some(Token::Sep))]);
229 len += 1;
230 }
231 Some((close, Token::CloseBracket)) => return Some((open, len, close)),
232 _ => return None,
233 }
234 }
235 }
236
237 fn next_matrix(&mut self, left: &'a str) -> Option<Matrix<'a>> {
238 let mut data = Vec::new();
239 let (open, num_cols, close) = self.next_matrix_row(&mut data)?;
240 loop {
241 match self.advance() {
242 Some((_, Token::Sep)) => {
243 let (no, ncols, nc) = self.next_matrix_row(&mut data)?;
244 if no != open || ncols != num_cols || nc != close {
245 return None;
246 }
247 }
248 Some((right, Token::CloseBracket))
249 if data.len() > 1 && open == left && close == right =>
250 {
251 return Some(Matrix::new(left, data, num_cols, right));
252 }
253 _ => return None,
254 }
255 }
256 }
257
258 fn next_script(&mut self) -> Script<'a> {
259 let mark = self.pos;
260 match self.advance() {
261 Some((_, Token::Super)) => Script::Super(self.next_simple(None).unwrap_or_default()),
262 Some((_, Token::Sub)) => {
263 let sub = self.next_simple(None).unwrap_or_default();
264 let mark = self.pos;
265 if let Some((_, Token::Super)) = self.advance() {
266 Script::Subsuper(sub, self.next_simple(None).unwrap_or_default())
267 } else {
268 self.pos = mark; Script::Sub(sub)
270 }
271 }
272 _ => {
273 self.pos = mark; Script::None
275 }
276 }
277 }
278
279 fn next_script_func(&mut self, stop: Option<Token>) -> Option<ScriptFunc<'a>> {
280 if self.depth >= MAX_DEPTH {
281 return None;
282 }
283 self.depth += 1;
284 let mark = self.pos;
285 let result = if let Some((func, Token::Function)) = self.advance() {
286 Some(
287 Func::new(
288 func,
289 self.next_script(),
290 self.next_script_func(None).unwrap_or_default(),
291 )
292 .into(),
293 )
294 } else {
295 self.pos = mark; self.next_simple(stop)
297 .map(|simp| SimpleScript::new(simp, self.next_script()).into())
298 };
299 self.depth -= 1;
300 result
301 }
302
303 fn next_intermediate(&mut self, stop: Option<Token>) -> Option<Intermediate<'a>> {
304 let base = self.next_script_func(stop)?;
305 let mark = self.pos;
306 if let Some((_, Token::Frac)) = self.advance() {
307 Some(Intermediate::Frac(Frac::new(
308 base,
309 self.next_script_func(None).unwrap_or_default(),
310 )))
311 } else {
312 self.pos = mark; Some(Intermediate::ScriptFunc(base))
314 }
315 }
316
317 fn parse(&mut self) -> Expression<'a> {
318 let mut inters = Vec::new();
319 let mut wraps = 0;
320 loop {
321 while let Some(inter) = self.next_intermediate(None) {
322 inters.push(inter);
323 }
324 match self.advance() {
325 Some((close, Token::CloseBracket)) => {
326 if wraps < MAX_DEPTH {
328 let group = Simple::Group(Group::new("", inters, close));
329 inters = vec![group.into()];
330 wraps += 1;
331 }
332 }
333 other => {
334 debug_assert!(other.is_none(), "didn't exhaust tokens");
336 break;
337 }
338 }
339 }
340 Expression::from(inters)
341 }
342}
343
344pub fn parse_tokens<'a, T>(tokens: T) -> Expression<'a>
346where
347 T: IntoIterator<Item = (&'a str, Token)>,
348{
349 Parser::new(tokens).parse()
350}
351
352#[must_use]
356pub fn parse(inp: &str) -> Expression<'_> {
357 parse_tokens(Tokenizer::new(inp))
358}
359
360#[cfg(test)]
361mod tests {
362 use crate::tree::{
363 Expression, Frac, Func, Group, Intermediate, Matrix, Simple, SimpleBinary, SimpleFunc,
364 SimpleScript, SimpleUnary,
365 };
366
367 #[test]
368 fn complex_precedence() {
369 let expr = super::parse("sin_a^b c_d / (abs h)_i^j");
370 let expected = [Frac::new(
371 Func::with_subsuper(
372 "sin",
373 Simple::Ident("a"),
374 Simple::Ident("b"),
375 SimpleScript::with_sub(Simple::Ident("c"), Simple::Ident("d")),
376 ),
377 SimpleScript::with_subsuper(
378 Group::from_iter("(", [SimpleUnary::new("abs", Simple::Ident("h"))], ")"),
379 Simple::Ident("i"),
380 Simple::Ident("j"),
381 ),
382 )]
383 .into_iter()
384 .collect();
385 assert_eq!(expr, expected);
386 }
387
388 #[test]
389 fn missing_sub() {
390 let expr = super::parse("a_");
391 let expected =
392 Expression::from_iter([SimpleScript::with_sub(Simple::Ident("a"), Simple::Missing)]);
393 assert_eq!(expr, expected);
394 }
395
396 #[test]
397 fn missing_super() {
398 let expr = super::parse("a^");
399 let expected = [SimpleScript::with_super(
400 Simple::Ident("a"),
401 Simple::Missing,
402 )]
403 .into_iter()
404 .collect();
405 assert_eq!(expr, expected);
406 }
407
408 #[test]
409 fn missing_group_subsuper() {
410 let expr = super::parse("(a_b^)");
412 let expected = [Group::from_iter(
413 "(",
414 [SimpleScript::with_subsuper(
415 Simple::Ident("a"),
416 Simple::Ident("b"),
417 Simple::Missing,
418 )],
419 ")",
420 )]
421 .into_iter()
422 .collect();
423 assert_eq!(expr, expected);
424 }
425
426 #[test]
427 fn missing_group_unary() {
428 let expr = super::parse("(sqrt)");
430 let expected = [Group::from_iter(
431 "(",
432 [SimpleUnary::new("sqrt", Simple::Missing)],
433 ")",
434 )]
435 .into_iter()
436 .collect();
437 assert_eq!(expr, expected);
438 }
439
440 #[test]
441 fn unmatched_close() {
442 let expr = super::parse(")");
443 let expected = [Group::new("", Expression::default(), ")")]
444 .into_iter()
445 .collect();
446 assert_eq!(expr, expected);
447 }
448
449 #[test]
450 fn simple_bracket_matching() {
451 let expr = super::parse("|a|");
452 let expected = [Group::from_iter("|", [Simple::Ident("a")], "|")]
453 .into_iter()
454 .collect();
455 assert_eq!(expr, expected);
456 }
457
458 #[test]
459 fn eager_bracket_matching() {
460 let expr = super::parse("|a|b|c|"); let expected = [
462 Group::from_iter("|", [Simple::Ident("a")], "|").into(),
463 Simple::Ident("b"),
464 Group::from_iter("|", [Simple::Ident("c")], "|").into(),
465 ]
466 .into_iter()
467 .collect();
468 assert_eq!(expr, expected);
469 }
470
471 #[test]
472 fn close_bracket_matching() {
473 let expr = super::parse("(a|b)c|d"); let expected = [
475 Group::from_iter(
476 "(",
477 [Simple::Ident("a"), Simple::Symbol("|"), Simple::Ident("b")],
478 ")",
479 )
480 .into(),
481 Simple::Ident("c"),
482 Simple::Symbol("|"),
483 Simple::Ident("d"),
484 ]
485 .into_iter()
486 .collect();
487 assert_eq!(expr, expected);
488 }
489
490 #[test]
491 fn open_close_nonempty() {
492 let expr = super::parse("| |");
493 let expected = [Simple::Symbol("|"), Simple::Symbol("|")]
494 .into_iter()
495 .collect();
496 assert_eq!(expr, expected);
497 }
498
499 #[test]
500 fn double_open_close() {
501 let expr = super::parse("||x||");
502 let expected = Expression::from_iter([Group::from_iter("||", [Simple::Ident("x")], "||")]);
503 assert_eq!(expr, expected);
504 }
505
506 #[test]
507 fn simple_function() {
508 let expr = super::parse("sin x");
509 let expected = [Func::without_scripts("sin", Simple::Ident("x"))]
510 .into_iter()
511 .collect();
512 assert_eq!(expr, expected);
513 }
514
515 #[test]
516 fn complex_function() {
517 let expr = super::parse("sin_cos a cos^b c");
518 let expected = [Func::with_sub(
519 "sin",
520 SimpleFunc::new("cos", Simple::Ident("a")),
521 Func::with_super("cos", Simple::Ident("b"), Simple::Ident("c")),
522 )]
523 .into_iter()
524 .collect();
525 assert_eq!(expr, expected);
526 }
527
528 #[test]
529 fn unary_power_precidence() {
530 let expr = super::parse("sin_a b^c / d");
531 let expected = [Intermediate::Frac(Frac::new(
532 Func::with_sub(
533 "sin",
534 Simple::Ident("a"),
535 SimpleScript::with_super(Simple::Ident("b"), Simple::Ident("c")),
536 ),
537 Simple::Ident("d"),
538 ))]
539 .into();
540 assert_eq!(expr, expected);
541 }
542
543 #[test]
544 fn matrix_parsing() {
545 let expr = super::parse("[[a, b], [c, d]]");
546 let expected = [Matrix::new(
547 "[",
548 [
549 [Simple::Ident("a")].into_iter().collect(),
550 [Simple::Ident("b")].into_iter().collect(),
551 [Simple::Ident("c")].into_iter().collect(),
552 [Simple::Ident("d")].into_iter().collect(),
553 ],
554 2,
555 "]",
556 )]
557 .into_iter()
558 .collect();
559 assert_eq!(expr, expected);
560 }
561
562 #[test]
563 fn no_singleton_matrix() {
564 let expr = super::parse("[[a]]");
565 let expected = [Group::from_iter(
566 "[",
567 [Group::from_iter("[", [Simple::Ident("a")], "]")],
568 "]",
569 )]
570 .into_iter()
571 .collect();
572 assert_eq!(expr, expected);
573 }
574
575 #[test]
576 fn sets_as_groups() {
577 let expr = super::parse("{(x, y), (a, b)}");
580 let expected = [Group::from_iter(
581 "{",
582 [
583 Group::from_iter(
584 "(",
585 [Simple::Ident("x"), Simple::Symbol(","), Simple::Ident("y")],
586 ")",
587 )
588 .into(),
589 Simple::Symbol(","),
590 Group::from_iter(
591 "(",
592 [Simple::Ident("a"), Simple::Symbol(","), Simple::Ident("b")],
593 ")",
594 )
595 .into(),
596 ],
597 "}",
598 )]
599 .into_iter()
600 .collect();
601 assert_eq!(expr, expected);
602 }
603
604 #[test]
605 fn simple_binary() {
606 let expr = super::parse("root 3");
607 let expected = [SimpleBinary::new(
608 "root",
609 Simple::Number("3"),
610 Simple::Missing,
611 )]
612 .into_iter()
613 .collect();
614 assert_eq!(expr, expected);
615 }
616
617 #[test]
618 fn raw_text() {
619 let expr = super::parse(r#""raw text""#);
620 let expected = Expression::from_iter([Simple::Text("raw text")]);
621 assert_eq!(expr, expected);
622 }
623
624 #[test]
625 fn bare_symbol() {
626 let expr = super::parse("alpha");
627 let expected = Expression::from_iter([Simple::Symbol("alpha")]);
628 assert_eq!(expr, expected);
629 }
630
631 #[test]
632 fn open_close_multiple_intermediates() {
633 let expr = super::parse("|a b|");
635 let expected = [Group::from_iter(
636 "|",
637 [Simple::Ident("a"), Simple::Ident("b")],
638 "|",
639 )]
640 .into_iter()
641 .collect();
642 assert_eq!(expr, expected);
643 }
644
645 #[test]
646 fn unclosed_groups() {
647 let expr = super::parse("[[a");
649 let expected = [Group::from_iter(
650 "[",
651 [Group::from_iter("[", [Simple::Ident("a")], "")],
652 "",
653 )]
654 .into_iter()
655 .collect();
656 assert_eq!(expr, expected);
657 }
658
659 #[test]
660 fn deep_nested_brackets_are_not_exponential() {
661 let depth = 150;
663 let input = format!("{}a{}", "(".repeat(depth), ")".repeat(depth));
664 let expr = super::parse(&input);
665 assert_eq!(expr.len(), 1);
666 }
667
668 #[test]
669 fn deep_unary_chain_does_not_overflow() {
670 let input = "sqrt ".repeat(100_000);
672 let expr = super::parse(&input);
673 assert!(!expr.is_empty());
674 }
675
676 #[test]
677 fn deep_function_chain_does_not_overflow() {
678 let input = "sin ".repeat(100_000);
680 let expr = super::parse(&input);
681 assert!(!expr.is_empty());
682 }
683
684 #[test]
685 fn many_unmatched_closes_are_capped() {
686 let input = ")".repeat(200_000);
688 let expr = super::parse(&input);
689 assert_eq!(expr.len(), 1);
690 let cloned = expr.clone();
691 assert_eq!(expr, cloned);
692 }
693
694 #[test]
695 fn ragged_matrix_is_group() {
696 let expr = super::parse("[[a, b], [c]]");
698 let expected = [Group::from_iter(
699 "[",
700 [
701 Group::from_iter(
702 "[",
703 [Simple::Ident("a"), Simple::Symbol(","), Simple::Ident("b")],
704 "]",
705 )
706 .into(),
707 Simple::Symbol(","),
708 Group::from_iter("[", [Simple::Ident("c")], "]").into(),
709 ],
710 "]",
711 )]
712 .into_iter()
713 .collect();
714 assert_eq!(expr, expected);
715 }
716
717 #[test]
718 fn single_row_matrix() {
719 let expr = super::parse("[[a, b]]");
721 let expected = [Matrix::new(
722 "[",
723 [
724 [Simple::Ident("a")].into_iter().collect(),
725 [Simple::Ident("b")].into_iter().collect(),
726 ],
727 2,
728 "]",
729 )]
730 .into_iter()
731 .collect();
732 assert_eq!(expr, expected);
733 }
734
735 #[test]
736 fn matrix_candidate_with_trailing_tokens_is_group() {
737 let expr = super::parse("[[a] b]");
739 let expected = [Group::from_iter(
740 "[",
741 [
742 Group::from_iter("[", [Simple::Ident("a")], "]").into(),
743 Simple::Ident("b"),
744 ],
745 "]",
746 )]
747 .into_iter()
748 .collect();
749 assert_eq!(expr, expected);
750 }
751
752 #[test]
753 fn matrix_row_with_bar() {
754 let expr = super::parse("[[a|b],[c|d]]");
756 let expected = [Matrix::new(
757 "[",
758 [
759 [Simple::Ident("a"), Simple::Symbol("|"), Simple::Ident("b")]
760 .into_iter()
761 .collect(),
762 [Simple::Ident("c"), Simple::Symbol("|"), Simple::Ident("d")]
763 .into_iter()
764 .collect(),
765 ],
766 1,
767 "]",
768 )]
769 .into_iter()
770 .collect();
771 assert_eq!(expr, expected);
772 }
773}