Skip to main content

Crate mathlex

Crate mathlex 

Source
Expand description

§mathlex

A mathematical expression parser for LaTeX and plain text notation, producing a language-agnostic Abstract Syntax Tree (AST).

§Overview

mathlex is a pure parsing library that converts mathematical expressions in LaTeX or plain text format into a well-defined AST. The library does NOT perform any evaluation or mathematical operations - interpretation of the AST is entirely the responsibility of consuming libraries.

§Features

  • LaTeX Parsing: Parse mathematical LaTeX notation
  • Plain Text Parsing: Parse standard mathematical expressions
  • Rich AST: Comprehensive AST for algebra, calculus, linear algebra, set theory, logic
  • Vector Calculus: Gradient, divergence, curl, Laplacian operators
  • Multiple Integrals: Double, triple, and closed path integrals
  • Set Theory: Union, intersection, quantifiers, logical connectives
  • Quaternions: Support for quaternion algebra with basis vectors i, j, k
  • Vector Notation: Multiple styles (bold, arrow, hat) with context awareness
  • Utilities: Variable extraction, substitution, string conversion

§Quick Start

§Basic Parsing

use mathlex::{parse, parse_latex, Expression, ExprKind, BinaryOp};

// Parse plain text
let expr = parse("2*x + sin(y)").unwrap();

// Parse LaTeX
let expr = parse_latex(r"\frac{1}{2}").unwrap();

// Verify the parsed structure
if let ExprKind::Binary { op: BinaryOp::Div, .. } = expr.kind {
    println!("Parsed as division");
}

§Vector Calculus

use mathlex::{parse_latex, Expression, ExprKind};

// Gradient operator
let grad = parse_latex(r"\nabla f").unwrap();
assert!(matches!(grad.kind, ExprKind::Gradient { .. }));

// Divergence of a vector field
let div = parse_latex(r"\nabla \cdot \mathbf{F}").unwrap();
assert!(matches!(div.kind, ExprKind::Divergence { .. }));

// Curl (cross product with nabla)
let curl = parse_latex(r"\nabla \times \mathbf{F}").unwrap();
assert!(matches!(curl.kind, ExprKind::Curl { .. }));

// Laplacian
let laplacian = parse_latex(r"\nabla^2 f").unwrap();
assert!(matches!(laplacian.kind, ExprKind::Laplacian { .. }));

§Vector Notation Styles

use mathlex::{parse_latex, Expression, ExprKind, VectorNotation};

// Bold vectors
let bold = parse_latex(r"\mathbf{v}").unwrap();
if let ExprKind::MarkedVector { notation, .. } = bold.kind {
    assert_eq!(notation, VectorNotation::Bold);
}

// Arrow vectors
let arrow = parse_latex(r"\vec{a}").unwrap();
if let ExprKind::MarkedVector { notation, .. } = arrow.kind {
    assert_eq!(notation, VectorNotation::Arrow);
}

// Hat notation (unit vectors)
let hat = parse_latex(r"\hat{n}").unwrap();
if let ExprKind::MarkedVector { notation, .. } = hat.kind {
    assert_eq!(notation, VectorNotation::Hat);
}

§Set Theory

use mathlex::{parse_latex, Expression, ExprKind};

// Set union
let union = parse_latex(r"A \cup B").unwrap();
assert!(matches!(union.kind, ExprKind::SetOperation { .. }));

// Set membership
let membership = parse_latex(r"x \in A").unwrap();
assert!(matches!(membership.kind, ExprKind::SetRelationExpr { .. }));

// Universal quantifier
let forall = parse_latex(r"\forall x P").unwrap();
assert!(matches!(forall.kind, ExprKind::ForAll { .. }));

// Logical connectives
let and = parse_latex(r"P \land Q").unwrap();
assert!(matches!(and.kind, ExprKind::Logical { .. }));

§Multiple Integrals

use mathlex::{parse_latex, Expression, ExprKind};

// Double integral
let double = parse_latex(r"\iint_R f dA").unwrap();
if let ExprKind::MultipleIntegral { dimension, .. } = double.kind {
    assert_eq!(dimension, 2);
}

// Triple integral
let triple = parse_latex(r"\iiint_V f dV").unwrap();
if let ExprKind::MultipleIntegral { dimension, .. } = triple.kind {
    assert_eq!(dimension, 3);
}

// Closed path integral
let closed = parse_latex(r"\oint_C F dr").unwrap();
assert!(matches!(closed.kind, ExprKind::ClosedIntegral { .. }));

§Quaternions

use mathlex::{Expression, ExprKind, MathConstant};

// Quaternion basis vectors are available as constants
let i = Expression::constant(MathConstant::I);
let j = Expression::constant(MathConstant::J);
let k = Expression::constant(MathConstant::K);

// Create quaternion expression programmatically
// 1 + 2i + 3j + 4k
let quat = ExprKind::Quaternion {
    real: Box::new(Expression::integer(1)),
    i: Box::new(Expression::integer(2)),
    j: Box::new(Expression::integer(3)),
    k: Box::new(Expression::integer(4)),
};

§Configuration

For advanced parsing options, use ParserConfig:

use mathlex::{parse_with_config, ParserConfig, NumberSystem};
use std::collections::HashSet;

let config = ParserConfig {
    implicit_multiplication: true,
    number_system: NumberSystem::Complex,
    ..Default::default()
};

// Parse with custom configuration
let expr = parse_with_config("2*x + 3", &config).unwrap();

§Context-Aware Parsing

The parser uses context awareness for certain symbols:

  • e: Parsed as Euler’s constant unless it appears in an exponent (where it’s treated as a variable for scientific notation)
  • i, j, k: Interpreted based on NumberSystem setting:
    • In Real: treated as variables
    • In Complex: i is the imaginary unit, j and k are variables
    • In Quaternion: i, j, k are quaternion basis vectors
use mathlex::{parse_latex, Expression, MathConstant};

// 'e' as Euler's constant
let euler = parse_latex(r"e").unwrap();
assert_eq!(euler, Expression::constant(MathConstant::E));

// 'i' as imaginary unit (when explicitly marked)
let imag = parse_latex(r"\mathrm{i}").unwrap();
assert_eq!(imag, Expression::constant(MathConstant::I));

§Parser Features

§Expression Subscripts

The LaTeX parser supports complex expression subscripts that are flattened into variable names:

use mathlex::{parse_latex, Expression};

// Simple subscript: x_i
let simple = parse_latex(r"x_i").unwrap();
assert_eq!(simple, Expression::variable("x_i".to_string()));

// Expression subscript: x_{i+1}
let expr_sub = parse_latex(r"x_{i+1}").unwrap();
assert_eq!(expr_sub, Expression::variable("x_iplus1".to_string()));

// Complex subscript: a_{n-1}
let complex = parse_latex(r"a_{n-1}").unwrap();
assert_eq!(complex, Expression::variable("a_nminus1".to_string()));

Supported subscript operators: + (plus), - (minus), * (times), / (div), ^ (pow)

§Derivative Notation

Both explicit and standard derivative notations are supported:

use mathlex::{parse_latex, Expression, ExprKind};

// Standard notation: d/dx followed by expression
let standard = parse_latex(r"\frac{d}{dx}f").unwrap();
assert!(matches!(standard.kind, ExprKind::Derivative { .. }));

// Explicit multiplication marker: d/d*x (when variable needs explicit marker)
let explicit = parse_latex(r"\frac{d}{d*x}f").unwrap();
assert!(matches!(explicit.kind, ExprKind::Derivative { .. }));

// Partial derivatives: ∂/∂x followed by expression
let partial = parse_latex(r"\frac{\partial}{\partial x}f").unwrap();
assert!(matches!(partial.kind, ExprKind::PartialDerivative { .. }));

// Higher order: d²/dx² followed by expression
let second = parse_latex(r"\frac{d^2}{dx^2}f").unwrap();
if let ExprKind::Derivative { order, .. } = second.kind {
    assert_eq!(order, 2);
}

§Design Philosophy

mathlex follows the principle of single responsibility:

  • Parse text into AST
  • Convert AST back to text (plain or LaTeX)
  • Query AST (find variables, functions)
  • Transform AST (substitution)

What mathlex does NOT do:

  • Evaluate expressions
  • Simplify expressions
  • Solve equations
  • Perform any mathematical computation

This design allows mathlex to serve as a shared foundation for both symbolic computation systems (like thales) and numerical libraries (like NumericSwift) without creating dependencies between them.

Re-exports§

pub use ast::AnnotationSet;
pub use ast::BinaryOp;
pub use ast::Direction;
pub use ast::ExprKind;
pub use ast::Expression;
pub use ast::IndexType;
pub use ast::InequalityOp;
pub use ast::IntegralBounds;
pub use ast::LogicalOp;
pub use ast::MathConstant;
pub use ast::MathFloat;
pub use ast::MultipleBounds;
pub use ast::NumberSet;
pub use ast::RelationOp;
pub use ast::SetOp;
pub use ast::SetRelation;
pub use ast::TensorIndex;
pub use ast::UnaryOp;
pub use ast::VectorNotation;
pub use context::parse_system;
pub use context::ExpressionContext;
pub use context::InputFormat;
pub use error::ParseError;
pub use error::ParseErrorKind;
pub use error::ParseOutput;
pub use error::ParseResult;
pub use error::Position;
pub use error::Span;
pub use latex::ToLatex;
pub use metadata::ContextSource;
pub use metadata::ExpressionMetadata;
pub use metadata::MathType;
pub use parser::parse;
pub use parser::parse_equation_system;
pub use parser::parse_latex;
pub use parser::parse_latex_equation_system;
pub use parser::parse_latex_lenient;
pub use parser::parse_lenient;
pub use parser::parse_lenient_with_config;

Modules§

ast
Abstract Syntax Tree (AST) Types
context
Context engine for multi-expression parsing.
display
Display Trait Implementations for AST (Plain Text)
error
Error types for mathlex parsing operations.
latex
LaTeX Conversion for AST
metadata
Expression metadata and type inference types.
parser
Parser module for mathlex.
util
AST Utility Functions

Structs§

ParserConfig
Configuration options for the mathematical expression parser.

Enums§

IndexConvention
Index convention for tensor notation.
NumberSystem
Number system context for parsing.

Constants§

VERSION
Placeholder for library version

Functions§

parse_with_config
Parses a plain text mathematical expression with custom configuration.