Skip to main content

asciimath_parser/
tree.rs

1//! The module containing all of the structures that defined a parsed representation of asciimath
2//!
3//! - [`Expression`] - A full expression containing a sequence of intermediate expressions
4//! - [`Intermediate`] - The most complicated single expression, this can be a high level fraction
5//! - [`Frac`] - A high level fraction, often parsed with a `/`
6//! - [`ScriptFunc`] - A scripted expression that can be a [`Func`] or just a simple expression
7//! - [`Func`] - A function like `sin` that can contain independent super- and subscripts
8//!   prior to its argument
9//! - [`SimpleScript`] - A simple expression that has super- and subscripts
10//! - [`Simple`] - A simple expression like a [`Symbol`][Simple::Symbol] or
11//!   [`Ident`][Simple::Ident]ifier
12//!
13//! The exceptions to this hierarchy are [`Group`] and [`Matrix`] that "reset" the hierarchy by
14//! wrapping expressions.
15use std::iter::FusedIterator;
16use std::ops::{Deref, Index};
17use std::slice::ChunksExact;
18
19/// A unary operator like "sqrt"
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct SimpleUnary<'a> {
22    /// The operator name
23    pub op: &'a str,
24    /// The operator argument
25    arg: Box<Simple<'a>>,
26}
27
28impl<'a> SimpleUnary<'a> {
29    /// Create a unary with its op and argument
30    pub fn new<S>(op: &'a str, arg: S) -> Self
31    where
32        S: Into<Simple<'a>>,
33    {
34        SimpleUnary {
35            op,
36            arg: Box::new(arg.into()),
37        }
38    }
39
40    /// The operator argument
41    #[must_use]
42    pub fn arg(&self) -> &Simple<'a> {
43        &self.arg
44    }
45}
46
47/// A simple func like "sin"
48///
49/// When encountering a func keyword while parsing a simple context, it can't have attached power
50/// arguments or complicated arguments, but it will still be parsed as a unary function.
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct SimpleFunc<'a> {
53    /// The function name
54    pub func: &'a str,
55    /// The function argument
56    arg: Box<Simple<'a>>,
57}
58
59impl<'a> SimpleFunc<'a> {
60    /// Create a simple function from its name and argument
61    pub fn new<S>(func: &'a str, arg: S) -> Self
62    where
63        S: Into<Simple<'a>>,
64    {
65        SimpleFunc {
66            func,
67            arg: Box::new(arg.into()),
68        }
69    }
70
71    /// The function argument
72    #[must_use]
73    pub fn arg(&self) -> &Simple<'a> {
74        &self.arg
75    }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
79/// A binary operator like "root"
80pub struct SimpleBinary<'a> {
81    /// The operator name
82    pub op: &'a str,
83    /// The first operator argument
84    first: Box<Simple<'a>>,
85    /// The second operator argument
86    second: Box<Simple<'a>>,
87}
88
89impl<'a> SimpleBinary<'a> {
90    /// Create a binary operator with its name and both arguments
91    pub fn new<F, S>(op: &'a str, first: F, second: S) -> Self
92    where
93        F: Into<Simple<'a>>,
94        S: Into<Simple<'a>>,
95    {
96        SimpleBinary {
97            op,
98            first: Box::new(first.into()),
99            second: Box::new(second.into()),
100        }
101    }
102
103    /// The first operator argument
104    #[must_use]
105    pub fn first(&self) -> &Simple<'a> {
106        &self.first
107    }
108
109    /// The second operator argument
110    #[must_use]
111    pub fn second(&self) -> &Simple<'a> {
112        &self.second
113    }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
117/// A bracketd group that allows inserting complicated expressions in simplex contexts
118///
119/// In some instances a bracket won't be parsed to close a group out, in that case the bracket will
120/// be the empty string.
121pub struct Group<'a> {
122    /// The left bracket
123    pub left_bracket: &'a str,
124    /// The grouped expression
125    pub expr: Expression<'a>,
126    /// The right bracket
127    pub right_bracket: &'a str,
128}
129
130impl<'a> Group<'a> {
131    /// Create a new group with two brackets and an expression
132    pub fn new<E: Into<Expression<'a>>>(
133        left_bracket: &'a str,
134        expr: E,
135        right_bracket: &'a str,
136    ) -> Self {
137        Group {
138            left_bracket,
139            expr: expr.into(),
140            right_bracket,
141        }
142    }
143
144    /// Create a new bracket with an iterable of intermediates instead of a fully formed expression
145    pub fn from_iter<T, I>(left_bracket: &'a str, inters: T, right_bracket: &'a str) -> Self
146    where
147        T: IntoIterator<Item = I>,
148        I: Into<Intermediate<'a>>,
149    {
150        Group {
151            left_bracket,
152            expr: inters.into_iter().collect(),
153            right_bracket,
154        }
155    }
156}
157
158/// A matrix e.g. "[[a, b], [x, y]]"
159///
160/// Individual expressions can be accessed with [rows][Matrix::rows] to get a random access iterator of row
161/// slices, or by indexing with a 2d array of indices in `[column, row]` order, e.g. `matrix[[0, 0]]`.
162/// Note that this is the opposite of the conventional `[row, column]` order used by libraries like
163/// ndarray and nalgebra.
164#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct Matrix<'a> {
166    /// The matrix's left bracket
167    pub left_bracket: &'a str,
168    /// The cells in the matrix in row-major order
169    cells: Box<[Expression<'a>]>,
170    /// The number of columns in the matrix
171    num_cols: usize,
172    /// The matrix's right bracket
173    pub right_bracket: &'a str,
174}
175
176impl<'a> Matrix<'a> {
177    /// Create a new matrix
178    ///
179    /// `cells` is a slice of expressiongs in row-major top-down order. `num_cols` is how many
180    /// columns exist in the final matrix.
181    ///
182    /// # Panics
183    /// When `num_cols` is zero, or when `cells.into().len()` is not divisible by `num_cols`.
184    pub fn new<E>(left_bracket: &'a str, cells: E, num_cols: usize, right_bracket: &'a str) -> Self
185    where
186        E: Into<Box<[Expression<'a>]>>,
187    {
188        let cells = cells.into();
189        assert!(num_cols > 0, "num_cols must be positive");
190        assert_eq!(cells.len() / num_cols * num_cols, cells.len());
191        Matrix {
192            left_bracket,
193            cells,
194            num_cols,
195            right_bracket,
196        }
197    }
198
199    /// The number of columns
200    #[must_use]
201    pub fn num_cols(&self) -> usize {
202        self.num_cols
203    }
204
205    /// The number of rows
206    #[must_use]
207    pub fn num_rows(&self) -> usize {
208        // num_cols is guaranteed positive by `Matrix::new`, so this never divides by zero
209        self.cells.len() / self.num_cols
210    }
211
212    /// The number of total cells
213    #[must_use]
214    pub fn num_cells(&self) -> usize {
215        self.cells.len()
216    }
217
218    /// A top-down iterator over rows as slices
219    #[must_use]
220    pub fn rows(&self) -> MatrixRows<'a, '_> {
221        MatrixRows(self.cells.chunks_exact(self.num_cols))
222    }
223
224    /// A top-down iterator over rows as slices
225    #[must_use]
226    pub fn iter(&self) -> MatrixRows<'a, '_> {
227        self.into_iter()
228    }
229}
230
231/// Matrix references iterate over rows
232impl<'a, 'b> IntoIterator for &'b Matrix<'a> {
233    type IntoIter = MatrixRows<'a, 'b>;
234    type Item = &'b [Expression<'a>];
235
236    fn into_iter(self) -> Self::IntoIter {
237        self.rows()
238    }
239}
240
241/// usize indices get rows
242impl<'a> Index<usize> for Matrix<'a> {
243    type Output = [Expression<'a>];
244
245    /// Get an individual expression
246    ///
247    /// # Panics
248    /// When index is out of bounds `idx >= num_rows`
249    fn index(&self, row: usize) -> &Self::Output {
250        self.rows().nth(row).expect("index out of bounds")
251    }
252}
253
254/// 2D indices get individual expressions
255impl<'a> Index<[usize; 2]> for Matrix<'a> {
256    type Output = Expression<'a>;
257
258    /// Get an individual expression
259    ///
260    /// The index is in `[column, row]` order — the opposite of the conventional `[row, column]`
261    /// order used by libraries like ndarray and nalgebra.
262    ///
263    /// # Panics
264    /// When indices are out of bounds `[x, y]`, `x >= num_cols`, `y >= num_rows`
265    fn index(&self, idx: [usize; 2]) -> &Self::Output {
266        let [x, y] = idx;
267        assert!(x < self.num_cols, "index out of bounds");
268        &self.cells[x + self.num_cols * y]
269    }
270}
271
272/// An iterator over rows of a matrix
273#[derive(Debug, Clone)]
274pub struct MatrixRows<'a, 'b>(ChunksExact<'b, Expression<'a>>);
275
276impl<'a, 'b> Iterator for MatrixRows<'a, 'b> {
277    type Item = &'b [Expression<'a>];
278
279    fn next(&mut self) -> Option<Self::Item> {
280        self.0.next()
281    }
282
283    fn size_hint(&self) -> (usize, Option<usize>) {
284        self.0.size_hint()
285    }
286
287    fn count(self) -> usize {
288        self.len()
289    }
290
291    fn nth(&mut self, n: usize) -> Option<Self::Item> {
292        self.0.nth(n)
293    }
294
295    fn last(mut self) -> Option<Self::Item> {
296        self.next_back()
297    }
298}
299impl FusedIterator for MatrixRows<'_, '_> {}
300
301impl DoubleEndedIterator for MatrixRows<'_, '_> {
302    fn next_back(&mut self) -> Option<Self::Item> {
303        self.0.next_back()
304    }
305
306    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
307        self.0.nth_back(n)
308    }
309}
310
311impl ExactSizeIterator for MatrixRows<'_, '_> {}
312
313/// A simple element of parsing
314///
315/// This is the lowest level in the parse tree, but can be scaled back up with a group or matrix
316#[derive(Default, Debug, Clone, PartialEq, Eq)]
317pub enum Simple<'a> {
318    /// A missing expression
319    ///
320    /// This is found in places where something didn't exist, e.g. "sin" by itself will have a
321    /// missing argument, but still be parsed.
322    #[default]
323    Missing,
324    /// A raw number
325    Number(&'a str),
326    /// Raw text
327    Text(&'a str),
328    /// An identity, usually a single character of something that doesn't have asciimath meaning
329    Ident(&'a str),
330    /// A recognized symbol
331    Symbol(&'a str),
332    /// A unary operator
333    Unary(SimpleUnary<'a>),
334    /// A simple unary function
335    Func(SimpleFunc<'a>),
336    /// A binary function
337    Binary(SimpleBinary<'a>),
338    /// A bracketed group
339    Group(Group<'a>),
340    /// A matrix
341    Matrix(Matrix<'a>),
342}
343
344impl Simple<'_> {
345    /// Get as an option where Missing is None
346    #[must_use]
347    pub fn as_option(&self) -> Option<&Self> {
348        match self {
349            Simple::Missing => None,
350            simple => Some(simple),
351        }
352    }
353}
354
355// macro to derive from for component types
356macro_rules! simple_from {
357    ($from:ty => $to:ident) => {
358        impl<'a> From<$from> for Simple<'a> {
359            fn from(inp: $from) -> Self {
360                Simple::$to(inp)
361            }
362        }
363    };
364}
365
366simple_from!(SimpleUnary<'a> => Unary);
367simple_from!(SimpleFunc<'a> => Func);
368simple_from!(SimpleBinary<'a> => Binary);
369simple_from!(Group<'a> => Group);
370simple_from!(Matrix<'a> => Matrix);
371
372/// scripts attached to some other object
373///
374/// Note that an object can have a script attached, but the corresponding [Simple] expression can
375/// still be [missing][Simple::Missing]. Objects with Scripts Deref to them so these raw objects
376/// probably aren't necessary.
377#[derive(Default, Debug, Clone, PartialEq, Eq)]
378pub enum Script<'a> {
379    /// No super or subscripts
380    #[default]
381    None,
382    /// Only a subscript
383    Sub(Simple<'a>),
384    /// Only a superscript
385    Super(Simple<'a>),
386    /// A sub and superscript
387    Subsuper(Simple<'a>, Simple<'a>),
388}
389
390impl<'a> Script<'a> {
391    /// Get the subscript
392    #[must_use]
393    pub fn sub(&self) -> Option<&Simple<'a>> {
394        match self {
395            Script::Sub(sub) | Script::Subsuper(sub, _) => Some(sub),
396            _ => None,
397        }
398    }
399
400    /// Get the superscript
401    #[must_use]
402    pub fn sup(&self) -> Option<&Simple<'a>> {
403        match self {
404            Script::Super(sup) | Script::Subsuper(_, sup) => Some(sup),
405            _ => None,
406        }
407    }
408}
409
410/// A simple expressiong with attached scripts
411#[derive(Default, Debug, Clone, PartialEq, Eq)]
412pub struct SimpleScript<'a> {
413    /// The simple argument
414    pub simple: Simple<'a>,
415    /// Any script modifications
416    pub script: Script<'a>,
417}
418
419impl<'a> SimpleScript<'a> {
420    /// Create a new simple script with a simple and script
421    pub fn new<S>(simple: S, script: Script<'a>) -> Self
422    where
423        S: Into<Simple<'a>>,
424    {
425        SimpleScript {
426            simple: simple.into(),
427            script,
428        }
429    }
430
431    /// Create an unscripted simple expression
432    pub fn without_scripts<S>(simple: S) -> Self
433    where
434        S: Into<Simple<'a>>,
435    {
436        Self::new(simple, Script::None)
437    }
438
439    /// Create a simple script with a subscript
440    pub fn with_sub<S, Sub>(simple: S, sub: Sub) -> Self
441    where
442        S: Into<Simple<'a>>,
443        Sub: Into<Simple<'a>>,
444    {
445        Self::new(simple, Script::Sub(sub.into()))
446    }
447
448    /// Create a simple script with a super script
449    pub fn with_super<S, Sup>(simple: S, sup: Sup) -> Self
450    where
451        S: Into<Simple<'a>>,
452        Sup: Into<Simple<'a>>,
453    {
454        Self::new(simple, Script::Super(sup.into()))
455    }
456
457    /// Create a simple script with sub and super scripts
458    pub fn with_subsuper<S, Sub, Sup>(simple: S, sub: Sub, sup: Sup) -> Self
459    where
460        S: Into<Simple<'a>>,
461        Sub: Into<Simple<'a>>,
462        Sup: Into<Simple<'a>>,
463    {
464        Self::new(simple, Script::Subsuper(sub.into(), sup.into()))
465    }
466}
467
468impl<'a, S> From<S> for SimpleScript<'a>
469where
470    S: Into<Simple<'a>>,
471{
472    fn from(inp: S) -> Self {
473        SimpleScript::without_scripts(inp.into())
474    }
475}
476
477/// Add sub and super
478impl<'a> Deref for SimpleScript<'a> {
479    type Target = Script<'a>;
480
481    fn deref(&self) -> &Self::Target {
482        &self.script
483    }
484}
485
486/// A full function that has complicated arguments and attached scripts
487#[derive(Debug, Clone, PartialEq, Eq)]
488pub struct Func<'a> {
489    /// The function name
490    pub func: &'a str,
491    /// Any script modifications of the function
492    pub script: Script<'a>,
493    /// The function argument
494    arg: Box<ScriptFunc<'a>>,
495}
496
497impl<'a> Func<'a> {
498    /// Create a new function with all attached parts
499    pub fn new<Arg>(func: &'a str, script: Script<'a>, arg: Arg) -> Self
500    where
501        Arg: Into<ScriptFunc<'a>>,
502    {
503        Func {
504            func,
505            script,
506            arg: Box::new(arg.into()),
507        }
508    }
509
510    /// Create a new function without scripts
511    pub fn without_scripts<Arg>(func: &'a str, arg: Arg) -> Self
512    where
513        Arg: Into<ScriptFunc<'a>>,
514    {
515        Self::new(func, Script::None, arg)
516    }
517
518    /// Create a new function with subscripts
519    pub fn with_sub<Sub, Arg>(func: &'a str, sub: Sub, arg: Arg) -> Self
520    where
521        Sub: Into<Simple<'a>>,
522        Arg: Into<ScriptFunc<'a>>,
523    {
524        Self::new(func, Script::Sub(sub.into()), arg)
525    }
526
527    /// Create a new function with superscripts
528    pub fn with_super<Sup, Arg>(func: &'a str, sup: Sup, arg: Arg) -> Self
529    where
530        Sup: Into<Simple<'a>>,
531        Arg: Into<ScriptFunc<'a>>,
532    {
533        Self::new(func, Script::Super(sup.into()), arg)
534    }
535
536    /// Create a new function with sub and superscripts
537    pub fn with_subsuper<Sub, Sup, Arg>(func: &'a str, sub: Sub, sup: Sup, arg: Arg) -> Self
538    where
539        Sub: Into<Simple<'a>>,
540        Sup: Into<Simple<'a>>,
541        Arg: Into<ScriptFunc<'a>>,
542    {
543        Self::new(func, Script::Subsuper(sub.into(), sup.into()), arg)
544    }
545
546    /// The function argument
547    #[must_use]
548    pub fn arg(&self) -> &ScriptFunc<'a> {
549        &self.arg
550    }
551}
552
553impl<'a> Deref for Func<'a> {
554    type Target = Script<'a>;
555
556    fn deref(&self) -> &Self::Target {
557        &self.script
558    }
559}
560
561/// A scripted object or a scripted function
562#[derive(Debug, Clone, PartialEq, Eq)]
563pub enum ScriptFunc<'a> {
564    /// A scripted simple expression
565    Simple(SimpleScript<'a>),
566    /// A function with sub abd superscripts
567    Func(Func<'a>),
568}
569
570impl Default for ScriptFunc<'_> {
571    fn default() -> Self {
572        ScriptFunc::Simple(SimpleScript::default())
573    }
574}
575
576impl<'a> From<Func<'a>> for ScriptFunc<'a> {
577    fn from(func: Func<'a>) -> Self {
578        ScriptFunc::Func(func)
579    }
580}
581
582impl<'a, S> From<S> for ScriptFunc<'a>
583where
584    S: Into<SimpleScript<'a>>,
585{
586    fn from(inp: S) -> Self {
587        ScriptFunc::Simple(inp.into())
588    }
589}
590
591/// A high level fraction
592#[derive(Debug, Clone, PartialEq, Eq)]
593pub struct Frac<'a> {
594    /// The numerator
595    pub numer: ScriptFunc<'a>,
596    /// The denominator
597    pub denom: ScriptFunc<'a>,
598}
599
600impl<'a> Frac<'a> {
601    /// Create a high level fraction
602    pub fn new<N, D>(numer: N, denom: D) -> Self
603    where
604        N: Into<ScriptFunc<'a>>,
605        D: Into<ScriptFunc<'a>>,
606    {
607        Frac {
608            numer: numer.into(),
609            denom: denom.into(),
610        }
611    }
612}
613
614/// An intermediate expression
615#[derive(Debug, Clone, PartialEq, Eq)]
616pub enum Intermediate<'a> {
617    /// A simple scripted object
618    ScriptFunc(ScriptFunc<'a>),
619    /// A fraction between scripted objects
620    Frac(Frac<'a>),
621}
622
623impl Default for Intermediate<'_> {
624    fn default() -> Self {
625        Intermediate::ScriptFunc(ScriptFunc::default())
626    }
627}
628
629impl<'a> From<Frac<'a>> for Intermediate<'a> {
630    fn from(frac: Frac<'a>) -> Self {
631        Intermediate::Frac(frac)
632    }
633}
634
635impl<'a, S> From<S> for Intermediate<'a>
636where
637    S: Into<ScriptFunc<'a>>,
638{
639    fn from(inp: S) -> Self {
640        Intermediate::ScriptFunc(inp.into())
641    }
642}
643
644/// A full expression
645///
646/// This is a sequence of intermediate expressions and Derefs to a slice of them.
647#[derive(Default, Debug, Clone, PartialEq, Eq)]
648pub struct Expression<'a>(Box<[Intermediate<'a>]>);
649
650impl<'a> Deref for Expression<'a> {
651    type Target = [Intermediate<'a>];
652
653    fn deref(&self) -> &Self::Target {
654        &self.0
655    }
656}
657
658impl<'a, I> FromIterator<I> for Expression<'a>
659where
660    I: Into<Intermediate<'a>>,
661{
662    fn from_iter<T>(iter: T) -> Self
663    where
664        T: IntoIterator<Item = I>,
665    {
666        Expression(iter.into_iter().map(std::convert::Into::into).collect())
667    }
668}
669
670impl<'a, B> From<B> for Expression<'a>
671where
672    B: Into<Box<[Intermediate<'a>]>>,
673{
674    fn from(inp: B) -> Self {
675        Expression(inp.into())
676    }
677}
678
679#[cfg(test)]
680mod tests {
681    use super::{
682        Expression, Frac, Func, Group, Intermediate, Matrix, Script, ScriptFunc, Simple,
683        SimpleBinary, SimpleFunc, SimpleScript, SimpleUnary,
684    };
685
686    #[test]
687    fn simple_unary() {
688        let unary = SimpleUnary::new("sqrt", Simple::Ident("x"));
689        assert_eq!(unary.op, "sqrt");
690        assert_eq!(unary.arg(), &Simple::Ident("x"));
691        assert_eq!(
692            Simple::from(unary),
693            Simple::Unary(SimpleUnary::new("sqrt", Simple::Ident("x")))
694        );
695    }
696
697    #[test]
698    fn simple_func() {
699        let func = SimpleFunc::new("sin", Simple::Ident("x"));
700        assert_eq!(func.func, "sin");
701        assert_eq!(func.arg(), &Simple::Ident("x"));
702        assert_eq!(
703            Simple::from(func),
704            Simple::Func(SimpleFunc::new("sin", Simple::Ident("x")))
705        );
706    }
707
708    #[test]
709    fn simple_binary() {
710        let binary = SimpleBinary::new("root", Simple::Number("3"), Simple::Ident("x"));
711        assert_eq!(binary.op, "root");
712        assert_eq!(binary.first(), &Simple::Number("3"));
713        assert_eq!(binary.second(), &Simple::Ident("x"));
714        assert_eq!(
715            Simple::from(binary),
716            Simple::Binary(SimpleBinary::new(
717                "root",
718                Simple::Number("3"),
719                Simple::Ident("x")
720            )),
721        );
722    }
723
724    #[test]
725    fn group() {
726        let from_expr = Group::new("(", Expression::from_iter([Simple::Ident("x")]), ")");
727        let from_inters = Group::from_iter("(", [Simple::Ident("x")], ")");
728        assert_eq!(from_expr, from_inters);
729        assert_eq!(from_expr.left_bracket, "(");
730        assert_eq!(from_expr.right_bracket, ")");
731        assert_eq!(from_expr.expr.len(), 1);
732        assert_eq!(Simple::from(from_expr.clone()), Simple::Group(from_expr));
733    }
734
735    fn cell(ident: &str) -> Expression<'_> {
736        Expression::from_iter([Simple::Ident(ident)])
737    }
738
739    #[test]
740    fn matrix() {
741        let matrix = Matrix::new("[", [cell("a"), cell("b"), cell("c"), cell("d")], 2, "]");
742        assert_eq!(matrix.left_bracket, "[");
743        assert_eq!(matrix.right_bracket, "]");
744        assert_eq!(matrix.num_cols(), 2);
745        assert_eq!(matrix.num_rows(), 2);
746        assert_eq!(matrix.num_cells(), 4);
747
748        let rows: Vec<_> = matrix.rows().collect();
749        assert_eq!(rows, [[cell("a"), cell("b")], [cell("c"), cell("d")]]);
750        assert_eq!(matrix.iter().count(), 2);
751        assert_eq!((&matrix).into_iter().count(), 2);
752
753        assert_eq!(matrix[0], [cell("a"), cell("b")]);
754        assert_eq!(matrix[1], [cell("c"), cell("d")]);
755        assert_eq!(matrix[[0, 0]], cell("a"));
756        assert_eq!(matrix[[1, 0]], cell("b"));
757        assert_eq!(matrix[[0, 1]], cell("c"));
758        assert_eq!(matrix[[1, 1]], cell("d"));
759
760        assert_eq!(Simple::from(matrix.clone()), Simple::Matrix(matrix));
761    }
762
763    #[test]
764    #[should_panic(expected = "index out of bounds")]
765    fn matrix_row_out_of_bounds() {
766        let matrix = Matrix::new("[", [cell("a"), cell("b")], 2, "]");
767        let _ = &matrix[1];
768    }
769
770    #[test]
771    #[should_panic(expected = "index out of bounds")]
772    fn matrix_col_out_of_bounds() {
773        let matrix = Matrix::new("[", [cell("a"), cell("b")], 2, "]");
774        let _ = &matrix[[2, 0]];
775    }
776
777    #[test]
778    #[should_panic(expected = "assertion")]
779    fn matrix_ragged() {
780        let _ = Matrix::new("[", [cell("a"), cell("b"), cell("c")], 2, "]");
781    }
782
783    #[test]
784    #[should_panic(expected = "num_cols must be positive")]
785    fn matrix_zero_cols() {
786        let _ = Matrix::new("[", [], 0, "]");
787    }
788
789    #[test]
790    fn matrix_rows_iterator() {
791        let matrix = Matrix::new("[", [cell("a"), cell("b"), cell("c"), cell("d")], 1, "]");
792        assert_eq!(matrix.rows().len(), 4);
793        assert_eq!(matrix.rows().size_hint(), (4, Some(4)));
794        assert_eq!(matrix.rows().nth(2), Some(&[cell("c")][..]));
795        assert_eq!(matrix.rows().last(), Some(&[cell("d")][..]));
796
797        let mut back = matrix.rows();
798        assert_eq!(back.next_back(), Some(&[cell("d")][..]));
799        assert_eq!(back.nth_back(1), Some(&[cell("b")][..]));
800    }
801
802    #[test]
803    fn simple_as_option() {
804        assert_eq!(Simple::Missing.as_option(), None);
805        assert_eq!(Simple::Ident("x").as_option(), Some(&Simple::Ident("x")));
806        assert_eq!(Simple::default(), Simple::Missing);
807    }
808
809    #[test]
810    fn script_accessors() {
811        assert_eq!(Script::default(), Script::None);
812        assert_eq!(Script::<'_>::None.sub(), None);
813        assert_eq!(Script::<'_>::None.sup(), None);
814
815        let sub = Script::Sub(Simple::Ident("i"));
816        assert_eq!(sub.sub(), Some(&Simple::Ident("i")));
817        assert_eq!(sub.sup(), None);
818
819        let sup = Script::Super(Simple::Number("2"));
820        assert_eq!(sup.sub(), None);
821        assert_eq!(sup.sup(), Some(&Simple::Number("2")));
822
823        let both = Script::Subsuper(Simple::Ident("i"), Simple::Number("2"));
824        assert_eq!(both.sub(), Some(&Simple::Ident("i")));
825        assert_eq!(both.sup(), Some(&Simple::Number("2")));
826    }
827
828    #[test]
829    fn simple_script() {
830        let none = SimpleScript::without_scripts(Simple::Ident("x"));
831        assert_eq!(none.simple, Simple::Ident("x"));
832        // Deref to Script
833        assert_eq!(none.sub(), None);
834        assert_eq!(none.sup(), None);
835        assert_eq!(SimpleScript::default().simple, Simple::Missing);
836
837        let sub = SimpleScript::with_sub(Simple::Ident("x"), Simple::Ident("i"));
838        assert_eq!(sub.sub(), Some(&Simple::Ident("i")));
839
840        let sup = SimpleScript::with_super(Simple::Ident("x"), Simple::Number("2"));
841        assert_eq!(sup.sup(), Some(&Simple::Number("2")));
842
843        let both = SimpleScript::with_subsuper(
844            Simple::Ident("x"),
845            Simple::Ident("i"),
846            Simple::Number("2"),
847        );
848        assert_eq!(both.sub(), Some(&Simple::Ident("i")));
849        assert_eq!(both.sup(), Some(&Simple::Number("2")));
850
851        // From any Into<Simple>
852        assert_eq!(SimpleScript::from(Simple::Ident("x")), none);
853    }
854
855    #[test]
856    fn func() {
857        let none = Func::without_scripts("sum", Simple::Ident("x"));
858        assert_eq!(none.func, "sum");
859        assert_eq!(none.arg(), &ScriptFunc::from(Simple::Ident("x")));
860        // Deref to Script
861        assert_eq!(none.sub(), None);
862
863        let sub = Func::with_sub("sum", Simple::Ident("i"), Simple::Ident("x"));
864        assert_eq!(sub.sub(), Some(&Simple::Ident("i")));
865
866        let sup = Func::with_super("sum", Simple::Number("n"), Simple::Ident("x"));
867        assert_eq!(sup.sup(), Some(&Simple::Number("n")));
868
869        let both = Func::with_subsuper(
870            "sum",
871            Simple::Ident("i"),
872            Simple::Number("n"),
873            Simple::Ident("x"),
874        );
875        assert_eq!(both.sub(), Some(&Simple::Ident("i")));
876        assert_eq!(both.sup(), Some(&Simple::Number("n")));
877    }
878
879    #[test]
880    fn script_func() {
881        let from_func = ScriptFunc::from(Func::without_scripts("sum", Simple::Ident("x")));
882        assert!(matches!(from_func, ScriptFunc::Func(_)));
883        let from_simple = ScriptFunc::from(Simple::Ident("x"));
884        assert!(matches!(from_simple, ScriptFunc::Simple(_)));
885        assert_eq!(
886            ScriptFunc::default(),
887            ScriptFunc::Simple(SimpleScript::default())
888        );
889    }
890
891    #[test]
892    fn frac_and_intermediate() {
893        let frac = Frac::new(Simple::Number("1"), Simple::Number("2"));
894        assert_eq!(frac.numer, ScriptFunc::from(Simple::Number("1")));
895        assert_eq!(frac.denom, ScriptFunc::from(Simple::Number("2")));
896
897        assert_eq!(Intermediate::from(frac.clone()), Intermediate::Frac(frac));
898        assert!(matches!(
899            Intermediate::from(Simple::Ident("x")),
900            Intermediate::ScriptFunc(_)
901        ));
902        assert!(matches!(
903            Intermediate::default(),
904            Intermediate::ScriptFunc(_)
905        ));
906    }
907
908    #[test]
909    fn expression() {
910        let expr = Expression::from_iter([Simple::Ident("x"), Simple::Ident("y")]);
911        // Deref to slice
912        assert_eq!(expr.len(), 2);
913        assert_eq!(expr[0], Intermediate::from(Simple::Ident("x")));
914        assert_eq!(Expression::default().len(), 0);
915
916        let boxed: Box<[Intermediate<'_>]> = Box::new([Intermediate::from(Simple::Ident("x"))]);
917        assert_eq!(Expression::from(boxed).len(), 1);
918    }
919}