Repository: nw-rs/citrus-cas (language: rust)

Issue:
more extensive and uniform tests
tests in different modules overlap in some areas, which should be separated or integrative. additionally, many test cases are not covered by the existing tests.


Discussion / hints:

Fix patch:
diff --git a/src/expression/expression_tree.rs b/src/expression/expression_tree.rs
index f3589d8..64108b6 100644
--- a/src/expression/expression_tree.rs
+++ b/src/expression/expression_tree.rs
@@ -262,7 +262,7 @@ impl fmt::Display for Atom {
         match self {
             Atom::Numeric(n) => write!(f, "{}", n),
             Atom::Variable(v) => write!(f, "{}", v),
-            Atom::Escape(e, n) => write!(f, "_{}{}", e, n),
+            Atom::Escape(e, n) => write!(f, "{}{}", e, n),
             Atom::Error(e) => write!(f, "{}", e),
         }
     }
@@ -933,25 +933,23 @@ impl fmt::Display for Expression {
             },
 
             Expression::Add(l, r) => write!(f, "{} + {}", l, r),
-            Expression::Subtract(l, r) => write!(f, "{} - {}", l, r),
+            Expression::Subtract(l, r) => match **r {
+                Expression::Atom(_)
+                | Expression::Matrix { .. }
+                | Expression::Vector { .. }
+                | Expression::Function { .. } => write!(f, "{} - {}", l, r),
+                _ => write!(f, "{} - ({})", l, r),
+            },
             Expression::Modulus(l, r) => write!(f, "{} % {}", l, r),
 
-            Expression::Multiply(l, r) | Expression::Divide(l, r) => {
+            Expression::Multiply(l, r) => {
                 match **l {
                     Expression::Add(_, _)
                     | Expression::Subtract(_, _)
                     | Expression::Modulus(_, _) => write!(f, "({})", l)?,
                     _ => write!(f, "{}", l)?,
                 };
-                write!(
-                    f,
-                    " {} ",
-                    match self {
-                        Expression::Multiply(_, _) => "*",
-                        Expression::Divide(_, _) => "/",
-                        _ => unreachable!(),
-                    }
-                )?;
+                write!(f, " * ")?;
                 match **r {
                     Expression::Add(_, _)
                     | Expression::Subtract(_, _)
@@ -960,6 +958,25 @@ impl fmt::Display for Expression {
                 }
             }
 
+            Expression::Divide(l, r) => {
+                match **l {
+                    Expression::Add(_, _)
+                    | Expression::Subtract(_, _)
+                    | Expression::Modulus(_, _)
+                    | Expression::Multiply(_, _)
+                    | Expression::Divide(_, _) => write!(f, "({})", l)?,
+                    _ => write!(f, "{}", l)?,
+                };
+                write!(f, " / ")?;
+                match **r {
+                    Expression::Add(_, _)
+                    | Expression::Subtract(_, _)
+                    | Expression::Modulus(_, _)
+                    | Expression::Multiply(_, _) => write!(f, "({})", r),
+                    _ => write!(f, "{}", r),
+                }
+            }
+
             Expression::Power(l, r) => {
                 match **l {
                     Expression::Add(_, _)
@@ -1039,20 +1056,889 @@ impl FromStr for Expression {
 mod tests {
     use core::str::FromStr;
 
-    use alloc::string::ToString;
+    use alloc::{boxed::Box, string::ToString, vec};
 
-    use crate::expression::expression_tree::{Atom, Numeric};
+    use crate::expression::expression_tree::{Atom, Escape, Numeric};
 
     use super::Expression;
 
     #[test]
     fn test_numeric_eq() {
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Integer(1))),
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(1.0)))
+        );
+
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Integer(1))),
+            Expression::Atom(Atom::Numeric(Numeric::Fraction(5, 5)))
+        );
+
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(0.5))),
+            Expression::Atom(Atom::Numeric(Numeric::Fraction(1, 2)))
+        );
+
         assert_ne!(
             Expression::Atom(Atom::Numeric(Numeric::Integer(1))),
             Expression::Atom(Atom::Numeric(Numeric::Decimal(1.2)))
         );
     }
 
+    #[test]
+    fn test_numeric_add() {
+        assert_eq!(
+            Numeric::Integer(1) + Numeric::Integer(1),
+            Numeric::Integer(2)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) + Numeric::Decimal(1.0),
+            Numeric::Decimal(2.0)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) + Numeric::Fraction(1, 2),
+            Numeric::Fraction(3, 2)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) + Numeric::Integer(1),
+            Numeric::Decimal(2.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) + Numeric::Decimal(1.0),
+            Numeric::Decimal(2.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) + Numeric::Fraction(1, 2),
+            Numeric::Decimal(1.5)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) + Numeric::Integer(1),
+            Numeric::Fraction(3, 2)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) + Numeric::Decimal(1.0),
+            Numeric::Decimal(1.5)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) + Numeric::Fraction(1, 2),
+            Numeric::Integer(1)
+        );
+    }
+
+    #[test]
+    fn test_numeric_sub() {
+        assert_eq!(
+            Numeric::Integer(1) - Numeric::Integer(1),
+            Numeric::Integer(0)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) - Numeric::Decimal(1.0),
+            Numeric::Decimal(0.0)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) - Numeric::Fraction(1, 2),
+            Numeric::Fraction(1, 2)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) - Numeric::Integer(1),
+            Numeric::Decimal(0.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) - Numeric::Decimal(1.0),
+            Numeric::Decimal(0.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) - Numeric::Fraction(1, 2),
+            Numeric::Decimal(0.5)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) - Numeric::Integer(1),
+            Numeric::Fraction(-1, 2)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) - Numeric::Decimal(1.0),
+            Numeric::Decimal(-0.5)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) - Numeric::Fraction(1, 2),
+            Numeric::Integer(0)
+        );
+    }
+
+    #[test]
+    fn test_numeric_mul() {
+        assert_eq!(
+            Numeric::Integer(1) * Numeric::Integer(1),
+            Numeric::Integer(1)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) * Numeric::Decimal(1.0),
+            Numeric::Decimal(1.0)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) * Numeric::Fraction(1, 2),
+            Numeric::Fraction(1, 2)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) * Numeric::Integer(1),
+            Numeric::Decimal(1.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) * Numeric::Decimal(1.0),
+            Numeric::Decimal(1.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) * Numeric::Fraction(1, 2),
+            Numeric::Decimal(0.5)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) * Numeric::Integer(1),
+            Numeric::Fraction(1, 2)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) * Numeric::Decimal(1.0),
+            Numeric::Decimal(0.5)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) * Numeric::Fraction(1, 2),
+            Numeric::Fraction(1, 4)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(22, 5) * Numeric::Fraction(1, 2),
+            Numeric::Fraction(11, 5)
+        );
+    }
+
+    #[test]
+    fn test_numeric_div() {
+        assert_eq!(
+            Numeric::Integer(1) / Numeric::Integer(1),
+            Numeric::Integer(1)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) / Numeric::Decimal(1.0),
+            Numeric::Decimal(1.0)
+        );
+
+        assert_eq!(
+            Numeric::Integer(1) / Numeric::Fraction(1, 2),
+            Numeric::Fraction(2, 1)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) / Numeric::Integer(1),
+            Numeric::Decimal(1.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) / Numeric::Decimal(1.0),
+            Numeric::Decimal(1.0)
+        );
+
+        assert_eq!(
+            Numeric::Decimal(1.0) / Numeric::Fraction(1, 2),
+            Numeric::Decimal(2.0)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) / Numeric::Integer(1),
+            Numeric::Fraction(1, 2)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) / Numeric::Decimal(1.0),
+            Numeric::Decimal(0.5)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(1, 2) / Numeric::Fraction(1, 2),
+            Numeric::Integer(1)
+        );
+
+        assert_eq!(
+            Numeric::Fraction(22, 5) / Numeric::Fraction(1, 2),
+            Numeric::Fraction(44, 5)
+        );
+    }
+
+    #[test]
+    fn test_numeric_fmt() {
+        assert_eq!(Numeric::Integer(1).to_string(), "1");
+        assert_eq!(Numeric::Integer(25).to_string(), "25");
+
+        assert_eq!(Numeric::Decimal(1.0).to_string(), "1");
+        assert_eq!(Numeric::Decimal(25.8).to_string(), "25.8");
+
+        assert_eq!(Numeric::Fraction(1, 2).to_string(), "(1 / 2)");
+        assert_eq!(Numeric::Fraction(25, 8).to_string(), "(25 / 8)");
+    }
+
+    #[test]
+    fn test_escape_fmt() {
+        assert_eq!(Escape::Atom.to_string(), "_A");
+        assert_eq!(Escape::Function.to_string(), "_F");
+        assert_eq!(Escape::Matrix.to_string(), "_M");
+        assert_eq!(Escape::Vector.to_string(), "_V");
+        assert_eq!(Escape::Everything.to_string(), "_*");
+    }
+
+    #[test]
+    fn test_atom_fmt() {
+        assert_eq!(Atom::Numeric(Numeric::Integer(1)).to_string(), "1");
+        assert_eq!(Atom::Numeric(Numeric::Integer(25)).to_string(), "25");
+
+        assert_eq!(Atom::Numeric(Numeric::Decimal(1.0)).to_string(), "1");
+        assert_eq!(Atom::Numeric(Numeric::Decimal(25.8)).to_string(), "25.8");
+
+        assert_eq!(
+            Atom::Numeric(Numeric::Fraction(1, 2)).to_string(),
+            "(1 / 2)"
+        );
+        assert_eq!(
+            Atom::Numeric(Numeric::Fraction(25, 8)).to_string(),
+            "(25 / 8)"
+        );
+
+        assert_eq!(Atom::Variable('x').to_string(), "x");
+        assert_eq!(Atom::Variable('y').to_string(), "y");
+
+        assert_eq!(Atom::Escape(Escape::Atom, 1).to_string(), "_A1");
+        assert_eq!(Atom::Escape(Escape::Function, 3).to_string(), "_F3");
+        assert_eq!(Atom::Escape(Escape::Matrix, 5).to_string(), "_M5");
+        assert_eq!(Atom::Escape(Escape::Vector, 7).to_string(), "_V7");
+        assert_eq!(Atom::Escape(Escape::Everything, 9).to_string(), "_*9");
+    }
+
+    #[test]
+    fn test_expression_simple_fmt() {
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Integer(1))).to_string(),
+            "1"
+        );
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Integer(25))).to_string(),
+            "25"
+        );
+
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(1.0))).to_string(),
+            "1"
+        );
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(25.8))).to_string(),
+            "25.8"
+        );
+
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Fraction(1, 2))).to_string(),
+            "(1 / 2)"
+        );
+        assert_eq!(
+            Expression::Atom(Atom::Numeric(Numeric::Fraction(25, 8))).to_string(),
+            "(25 / 8)"
+        );
+
+        assert_eq!(Expression::Atom(Atom::Variable('x')).to_string(), "x");
+        assert_eq!(Expression::Atom(Atom::Variable('y')).to_string(), "y");
+
+        assert_eq!(
+            Expression::Atom(Atom::Escape(Escape::Atom, 1)).to_string(),
+            "_A1"
+        );
+        assert_eq!(
+            Expression::Atom(Atom::Escape(Escape::Function, 3)).to_string(),
+            "_F3"
+        );
+        assert_eq!(
+            Expression::Atom(Atom::Escape(Escape::Matrix, 5)).to_string(),
+            "_M5"
+        );
+        assert_eq!(
+            Expression::Atom(Atom::Escape(Escape::Vector, 7)).to_string(),
+            "_V7"
+        );
+        assert_eq!(
+            Expression::Atom(Atom::Escape(Escape::Everything, 9)).to_string(),
+            "_*9"
+        );
+
+        assert_eq!(
+            Expression::Function {
+                name: "x".to_string(),
+                args: vec![Box::new(Expression::Atom(Atom::Variable('y')))]
+            }
+            .to_string(),
+            "x(y)"
+        );
+
+        assert_eq!(
+            Expression::Function {
+                name: "x".to_string(),
+                args: vec![
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ]
+            }
+            .to_string(),
+            "x(y, z)"
+        );
+
+        assert_eq!(
+            Expression::Negate(Box::new(Expression::Atom(Atom::Variable('x')))).to_string(),
+            "-x"
+        );
+
+        assert_eq!(
+            Expression::Factorial(Box::new(Expression::Atom(Atom::Variable('y')))).to_string(),
+            "y!"
+        );
+
+        assert_eq!(
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x ^ y"
+        );
+
+        assert_eq!(
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x * y"
+        );
+
+        assert_eq!(
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x / y"
+        );
+
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x + y"
+        );
+
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x - y"
+        );
+
+        assert_eq!(
+            Expression::Modulus(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x % y"
+        );
+
+        assert_eq!(
+            Expression::Matrix {
+                backing: vec![Box::new(Expression::Atom(Atom::Variable('x')))],
+                shape: (1, 1)
+            }
+            .to_string(),
+            "[x]"
+        );
+
+        assert_eq!(
+            Expression::Matrix {
+                backing: vec![
+                    Box::new(Expression::Atom(Atom::Variable('x'))),
+                    Box::new(Expression::Atom(Atom::Variable('y')))
+                ],
+                shape: (1, 2)
+            }
+            .to_string(),
+            "[x, y]"
+        );
+
+        assert_eq!(
+            Expression::Matrix {
+                backing: vec![
+                    Box::new(Expression::Atom(Atom::Variable('x'))),
+                    Box::new(Expression::Atom(Atom::Variable('y')))
+                ],
+                shape: (2, 1)
+            }
+            .to_string(),
+            "[x; y]"
+        );
+
+        assert_eq!(
+            Expression::Matrix {
+                backing: vec![
+                    Box::new(Expression::Atom(Atom::Variable('x'))),
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z'))),
+                    Box::new(Expression::Atom(Atom::Variable('w')))
+                ],
+                shape: (2, 2)
+            }
+            .to_string(),
+            "[x, y; z, w]"
+        );
+
+        assert_eq!(
+            Expression::Vector {
+                backing: vec![Box::new(Expression::Atom(Atom::Variable('x')))],
+                size: 1
+            }
+            .to_string(),
+            "<x>"
+        );
+
+        assert_eq!(
+            Expression::Vector {
+                backing: vec![
+                    Box::new(Expression::Atom(Atom::Variable('x'))),
+                    Box::new(Expression::Atom(Atom::Variable('y')))
+                ],
+                size: 2
+            }
+            .to_string(),
+            "<x, y>"
+        );
+
+        assert_eq!(
+            Expression::Vector {
+                backing: vec![
+                    Box::new(Expression::Atom(Atom::Variable('x'))),
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ],
+                size: 3
+            }
+            .to_string(),
+            "<x, y, z>"
+        );
+    }
+
+    #[test]
+    fn test_expression_add_fmt() {
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x + y"
+        );
+
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x + y + z"
+        );
+
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Subtract(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x + y - z"
+        );
+
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x + y * z"
+        );
+
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Divide(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x + y / z"
+        );
+
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Power(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x + y ^ z"
+        );
+
+        assert_eq!(
+            Expression::Add(
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                )),
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+            )
+            .to_string(),
+            "y + z + x"
+        );
+    }
+
+    #[test]
+    fn test_expression_subtract_fmt() {
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x - y"
+        );
+
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Subtract(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x - (y - z)"
+        );
+
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x - (y + z)"
+        );
+
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x - (y * z)"
+        );
+
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Divide(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x - (y / z)"
+        );
+
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Power(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x - (y ^ z)"
+        );
+
+        assert_eq!(
+            Expression::Subtract(
+                Box::new(Expression::Subtract(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                )),
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+            )
+            .to_string(),
+            "y - z - x"
+        );
+    }
+
+    #[test]
+    fn test_expression_multiply_fmt() {
+        assert_eq!(
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x * y"
+        );
+
+        assert_eq!(
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Subtract(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x * (y - z)"
+        );
+
+        assert_eq!(
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x * (y + z)"
+        );
+
+        assert_eq!(
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x * y * z"
+        );
+
+        assert_eq!(
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Divide(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x * y / z"
+        );
+
+        assert_eq!(
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Power(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x * y ^ z"
+        );
+    }
+
+    #[test]
+    fn test_expression_divide_fmt() {
+        assert_eq!(
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x / y"
+        );
+
+        assert_eq!(
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Subtract(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x / (y - z)"
+        );
+
+        assert_eq!(
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x / (y + z)"
+        );
+
+        assert_eq!(
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x / (y * z)"
+        );
+
+        assert_eq!(
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Divide(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x / y / z"
+        );
+
+        assert_eq!(
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Power(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x / y ^ z"
+        );
+    }
+
+    #[test]
+    fn test_expression_power_fmt() {
+        assert_eq!(
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Atom(Atom::Variable('y')))
+            )
+            .to_string(),
+            "x ^ y"
+        );
+
+        assert_eq!(
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Subtract(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x ^ (y - z)"
+        );
+
+        assert_eq!(
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x ^ (y + z)"
+        );
+
+        assert_eq!(
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x ^ (y * z)"
+        );
+
+        assert_eq!(
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Divide(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x ^ (y / z)"
+        );
+
+        assert_eq!(
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Variable('x'))),
+                Box::new(Expression::Power(
+                    Box::new(Expression::Atom(Atom::Variable('y'))),
+                    Box::new(Expression::Atom(Atom::Variable('z')))
+                ))
+            )
+            .to_string(),
+            "x ^ y ^ z"
+        );
+    }
+
     #[test]
     fn test_fmt_parse() {
         assert_eq!(
diff --git a/src/expression/latex.rs b/src/expression/latex.rs
index 4896ae7..c1f2c7a 100644
--- a/src/expression/latex.rs
+++ b/src/expression/latex.rs
@@ -399,10 +399,194 @@ pub fn latexify(expr: &Expression) -> String {
 mod tests {
     use alloc::{boxed::Box, string::ToString, vec};
 
-    use crate::expression::expression_tree::{Atom, Expression, Numeric};
+    use crate::expression::expression_tree::{Atom, Escape, Expression, Numeric};
 
     use super::{latexify, parse};
 
+    #[test]
+    fn latex_test_add() {
+        assert_eq!(
+            parse("1 + 2"),
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_subtract() {
+        assert_eq!(
+            parse("1 - 2"),
+            Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_add_negative() {
+        assert_eq!(
+            parse("1 + -2"),
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Negate(Box::new(Expression::Atom(
+                    Atom::Numeric(Numeric::Integer(2))
+                ))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_modulus() {
+        assert_eq!(
+            parse("1 % 2"),
+            Expression::Modulus(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_multiply() {
+        assert_eq!(
+            parse("1\\cdot2"),
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_divide() {
+        assert_eq!(
+            parse("1 / 2"),
+            Expression::Divide(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_multiply_negative() {
+        assert_eq!(
+            parse("1\\cdot-2"),
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Negate(Box::new(Expression::Atom(
+                    Atom::Numeric(Numeric::Integer(2))
+                ))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_exponent() {
+        assert_eq!(
+            parse("1 ^ 2"),
+            Expression::Power(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_factorial() {
+        assert_eq!(
+            parse("5!"),
+            Expression::Factorial(Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(
+                5
+            )))))
+        );
+    }
+
+    #[test]
+    fn latex_test_parentheses() {
+        assert_eq!(
+            parse("(1 + 2)\\cdot5"),
+            Expression::Multiply(
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+                )),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5))))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_nested_parentheses() {
+        assert_eq!(
+            parse("(5 \\cdot (4 + (6 / 3)))"),
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(4)))),
+                    Box::new(Expression::Divide(
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6)))),
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(3))))
+                    ))
+                ))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_spaceless() {
+        assert_eq!(
+            parse("1+2\\cdot5"),
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5))))
+                ))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_whitespace() {
+        assert_eq!(
+            parse(" 1    +  2 \\cdot   5  "),
+            Expression::Add(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5))))
+                ))
+            )
+        );
+    }
+
+    #[test]
+    fn latex_test_multi_level_expression() {
+        assert_eq!(
+            parse("1 \\cdot 2 + 3 / 4 ^ 6 % 7"),
+            Expression::Add(
+                Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
+                )),
+                Box::new(Expression::Modulus(
+                    Box::new(Expression::Divide(
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(3)))),
+                        Box::new(Expression::Power(
+                            Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(4)))),
+                            Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6))))
+                        ))
+                    )),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(7))))
+                ))
+            )
+        );
+    }
+
     #[test]
     fn complex_latex() {
         assert_eq!(
@@ -456,11 +640,326 @@ mod tests {
         )
     }
 
+    #[test]
+    fn latex_test_integer() {
+        assert_eq!(
+            parse("1"),
+            Expression::Atom(Atom::Numeric(Numeric::Integer(1)))
+        );
+        assert_eq!(
+            parse("55"),
+            Expression::Atom(Atom::Numeric(Numeric::Integer(55)))
+        );
+    }
+
+    #[test]
+    fn latex_test_decimal() {
+        assert_eq!(
+            parse("1.0"),
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(1.0)))
+        );
+    }
+
+    #[test]
+    fn latex_test_escape() {
+        assert_eq!(
+            parse("_A2"),
+            Expression::Atom(Atom::Escape(Escape::Atom, 2))
+        );
+    }
+
+    #[test]
+    fn latex_test_wildcard_escape() {
+        assert_eq!(
+            parse("_*0"),
+            Expression::Atom(Atom::Escape(Escape::Everything, 0))
+        );
+    }
+
+    #[test]
+    fn latex_test_variable() {
+        assert_eq!(parse("x"), Expression::Atom(Atom::Variable('x')));
+    }
+
+    #[test]
+    fn latex_test_unicode_variable() {
+        assert_eq!(parse("π"), Expression::Atom(Atom::Variable('π')));
+    }
+
+    #[test]
+    fn latex_test_function() {
+        assert_eq!(
+            parse("\\sin(1 + -2)"),
+            Expression::Function {
+                name: "sin".to_string(),
+                args: vec![Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Negate(Box::new(Expression::Atom(
+                        Atom::Numeric(Numeric::Integer(2))
+                    ))))
+                )),]
+                .into_iter()
+                .collect(),
+            }
+        );
+    }
+
+    #[test]
+    fn latex_test_function_empty() {
+        assert_eq!(
+            parse("\\sin()"),
+            Expression::Function {
+                name: "sin".to_string(),
+                args: vec![].into_iter().collect(),
+            }
+        );
+    }
+
+    #[test]
+    fn latex_test_multiple_arguments() {
+        assert_eq!(
+            parse("normcdf(0, 1, 2.5, x)"),
+            Expression::Function {
+                name: "normcdf".to_string(),
+                args: vec![
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(0)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Decimal(2.5)))),
+                    Box::new(Expression::Atom(Atom::Variable('x'))),
+                ]
+                .into_iter()
+                .collect(),
+            }
+        );
+    }
+
+    #[test]
+    fn latex_test_advanced_function() {
+        assert_eq!(
+            parse("5 \\cdot \\log(10, \\sin(x))"),
+            Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Function {
+                    name: "log".to_string(),
+                    args: vec![
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(10)))),
+                        Box::new(Expression::Function {
+                            name: "sin".to_string(),
+                            args: vec![Box::new(Expression::Atom(Atom::Variable('x'))),]
+                                .into_iter()
+                                .collect(),
+                        }),
+                    ]
+                    .into_iter()
+                    .collect(),
+                })
+            )
+        );
+    }
+
+    #[test]
+    fn integer_string_latex() {
+        assert_eq!(
+            "5",
+            latexify(&Expression::Atom(Atom::Numeric(Numeric::Integer(5))))
+        );
+    }
+
+    #[test]
+    fn decimal_string_latex() {
+        assert_eq!(
+            "5",
+            latexify(&Expression::Atom(Atom::Numeric(Numeric::Decimal(5.0))))
+        );
+        assert_eq!(
+            "5.7",
+            latexify(&Expression::Atom(Atom::Numeric(Numeric::Decimal(5.7))))
+        );
+    }
+
+    #[test]
+    fn variable_string_latex() {
+        assert_eq!("x", latexify(&Expression::Atom(Atom::Variable('x'))));
+    }
+
+    #[test]
+    fn unicode_variable_string_latex() {
+        assert_eq!("π", latexify(&Expression::Atom(Atom::Variable('π'))));
+    }
+
+    #[test]
+    fn escape_string_latex() {
+        assert_eq!(
+            "_A2",
+            latexify(&Expression::Atom(Atom::Escape(Escape::Atom, 2)))
+        );
+    }
+
+    #[test]
+    fn wildcard_escape_string_latex() {
+        assert_eq!(
+            "_*0",
+            latexify(&Expression::Atom(Atom::Escape(Escape::Everything, 0)))
+        );
+    }
+
+    #[test]
+    fn negate_string_latex() {
+        assert_eq!(
+            "-5",
+            latexify(&Expression::Negate(Box::new(Expression::Atom(
+                Atom::Numeric(Numeric::Integer(5))
+            ))))
+        );
+    }
+
+    #[test]
+    fn add_string_latex() {
+        assert_eq!(
+            "5+6",
+            latexify(&Expression::Add(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6))))
+            ))
+        );
+    }
+
+    #[test]
+    fn subtract_string_latex() {
+        assert_eq!(
+            "5-6",
+            latexify(&Expression::Subtract(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6))))
+            ))
+        );
+    }
+
+    #[test]
+    fn multiply_string_latex() {
+        assert_eq!(
+            "5\\cdot6",
+            latexify(&Expression::Multiply(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6))))
+            ))
+        );
+    }
+
+    #[test]
+    fn divide_string_latex() {
+        assert_eq!(
+            "\\frac{5}{6}",
+            latexify(&Expression::Divide(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6))))
+            ))
+        );
+    }
+
+    #[test]
+    fn power_string_latex() {
+        assert_eq!(
+            "5^6",
+            latexify(&Expression::Power(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6))))
+            ))
+        );
+    }
+
+    #[test]
+    fn complex_power_string_latex() {
+        assert_eq!(
+            "5^{6^7}",
+            latexify(&Expression::Power(
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                Box::new(Expression::Power(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(7))))
+                ))
+            ))
+        );
+    }
+
+    #[test]
+    fn factorial_string_latex() {
+        assert_eq!(
+            "5!",
+            latexify(&Expression::Factorial(Box::new(Expression::Atom(
+                Atom::Numeric(Numeric::Integer(5))
+            ))))
+        );
+    }
+
+    #[test]
+    fn function_string_latex() {
+        assert_eq!(
+            "\\sin\\left(5\\right)",
+            latexify(&Expression::Function {
+                name: "sin".to_string(),
+                args: vec![Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(
+                    5
+                ))))]
+                .into_iter()
+                .collect(),
+            })
+        );
+    }
+
+    #[test]
+    fn function_string_latex_empty() {
+        assert_eq!(
+            "\\sin\\left(\\right)",
+            latexify(&Expression::Function {
+                name: "sin".to_string(),
+                args: vec![].into_iter().collect(),
+            })
+        );
+    }
+
+    #[test]
+    fn function_string_latex_multiple() {
+        assert_eq!(
+            "\\sin\\left(5,6\\right)",
+            latexify(&Expression::Function {
+                name: "sin".to_string(),
+                args: vec![
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6)))),
+                ]
+                .into_iter()
+                .collect(),
+            })
+        );
+    }
+
+    #[test]
+    fn function_string_latex_advanced() {
+        assert_eq!(
+            "\\sin\\left(5\\cdot\\log\\left(6\\right)\\right)",
+            latexify(&Expression::Function {
+                name: "sin".to_string(),
+                args: vec![Box::new(Expression::Multiply(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
+                    Box::new(Expression::Function {
+                        name: "log".to_string(),
+                        args: vec![Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(
+                            6
+                        ))))],
+                    })
+                ))]
+                .into_iter()
+                .collect(),
+            })
+        );
+    }
+
     #[test]
     fn complex_string_latex() {
         assert_eq!(
             "\\frac{5}{6}\\cdot5+4^{2+x}-1!+arc\\left(6\\right)",
-            crate::expression::latex::latexify(&Expression::Add(
+            latexify(&Expression::Add(
                 Box::new(Expression::Subtract(
                     Box::new(Expression::Add(
                         Box::new(Expression::Multiply(
diff --git a/src/expression/parser.rs b/src/expression/parser.rs
index 8688ee7..dc323e2 100644
--- a/src/expression/parser.rs
+++ b/src/expression/parser.rs
@@ -261,6 +261,14 @@ mod tests {
             parse("1.0"),
             Expression::Atom(Atom::Numeric(Numeric::Decimal(1.0)))
         );
+        assert_eq!(
+            parse("55.0"),
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(55.0)))
+        );
+        assert_eq!(
+            parse("55.5"),
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(55.5)))
+        );
     }
 
     #[test]
@@ -269,13 +277,21 @@ mod tests {
             parse("_A2"),
             Expression::Atom(Atom::Escape(Escape::Atom, 2))
         );
-    }
-
-    #[test]
-    fn test_wildcard_escape() {
         assert_eq!(
-            parse("_*0"),
-            Expression::Atom(Atom::Escape(Escape::Everything, 0))
+            parse("_*1"),
+            Expression::Atom(Atom::Escape(Escape::Everything, 1))
+        );
+        assert_eq!(
+            parse("_V2"),
+            Expression::Atom(Atom::Escape(Escape::Vector, 2))
+        );
+        assert_eq!(
+            parse("_M3"),
+            Expression::Atom(Atom::Escape(Escape::Matrix, 3))
+        );
+        assert_eq!(
+            parse("_F4"),
+            Expression::Atom(Atom::Escape(Escape::Function, 4))
         );
     }
 


Test patch: