Contents

ChrisGVE/mathlex

Mathematical expression parser for LaTeX and plain text notation, producing a language-agnostic AST

Features

  • LaTeX Parsing - Parse mathematical LaTeX notation (\frac{1}{2}, \int_0^1, \sum_{i=1}^n)
  • Plain Text Parsing - Parse standard math notation (2*x + 3, sin(x))
  • Rich AST - Comprehensive AST supporting:

- Algebra and calculus expressions - Linear algebra (vectors and matrices) - Vector calculus (gradient, divergence, curl, Laplacian) - Set theory (unions, intersections, quantifiers) - Logic (connectives, quantifiers) - Multiple integrals (double, triple, closed path) - Quaternion algebra

  • Vector Notation - Multiple styles: bold (\mathbf{v}), arrow (\vec{v}), hat (\hat{n})
  • Context-Aware - Smart handling of e, i, j, k based on number system context
  • No Evaluation - Pure parsing library, interpretation is client responsibility
  • Cross-Platform - Native support for Rust and Swift (iOS/macOS)

Installation

Rust

Add to your Cargo.toml:

[dependencies]
mathlex = "0.3.4"

Swift

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/ChrisGVE/mathlex.git", from: "0.3.4")
]

Or in Xcode: File → Add Package Dependencies → Enter https://github.com/ChrisGVE/mathlex.git

Quick Start

Rust

Parse Plain Text
use mathlex::{parse, Expression};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let expr = parse("2*x + sin(y)")?;

    // Find all variables
    let vars = expr.find_variables();
    println!("Variables: {:?}", vars); // {"x", "y"}

    // Convert back to string
    println!("{}", expr); // "2 * x + sin(y)"

    Ok(())
}
Parse LaTeX
use mathlex::{parse_latex, Expression};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let expr = parse_latex(r"\frac{1}{2} + \sqrt{x}")?;

    // Convert to LaTeX string
    println!("{}", expr.to_latex()); // "\frac{1}{2} + \sqrt{x}"

    Ok(())
}

Swift

import MathLex

do {
    // Parse plain text
    let expr = try MathExpression.parse("2*x + sin(y)")
    print(expr.variables) // ["x", "y"]
    print(expr.description) // "2 * x + sin(y)"

    // Parse LaTeX
    let latex = try MathExpression.parseLatex(#"\frac{1}{2}"#)
    print(latex.latex) // "\frac{1}{2}"
} catch {
    print("Parse error: \(error)")
}

Supported Notation

Literals

  • Integers: 42, -17
  • Floats: 3.14, 2.5e-3
  • Rationals: LaTeX \frac{1}{2}
  • Complex: via construction
  • Quaternions: via construction with basis vectors i, j, k

Symbols

  • Variables: x, y, theta
  • Greek letters: \alpha, \beta, \Gamma
  • Constants: \pi (π), e, \infty (∞)
  • Imaginary/quaternion units: i, j, k (context-aware)

Operations

  • Binary: +, -, , /, ^, *, %, \pm, \mp
  • Unary: -x, x!
  • Functions: sin, cos, tan, log, ln, exp, sqrt, abs, floor, ceil, det
  • Vector products: \cdot (dot), \times (cross)

Calculus (Representation Only)

  • Derivatives (LaTeX):

- Standard notation: \frac{d}{dx}f, \frac{\partial}{\partial x}f - Higher order: \frac{d^2}{dx^2}f, \frac{\partial^2}{\partial x^2}f

  • Derivatives (plain text):

- Leibniz: dy/dx, d2y/dx2, d3y/dx3 - Prime: y', y'', y''' - Functional: diff(y, x), diff(y, x, 2)

  • Partial derivatives (plain text):

- partial(f, x), partial(f, x, 2) (second order) - partial(f, x, y) (mixed partial ∂²f/∂x∂y)

  • Integrals: \int, \int_a^b
  • Multiple integrals: \iint (double), \iiint (triple)
  • Closed integrals: \oint (line), \oiint (surface)
  • Limits: \lim_{x \to a}
  • Sums: \sum_{i=1}^{n}
  • Products: \prod_{i=1}^{n}
  • Subscripts: Supports expression subscripts like x_{i+1}, a_{n-1} (flattened to variable names)

Vector Calculus

  • Gradient: \nabla f (LaTeX), grad(f), nabla(f), ∇f (plain text)
  • Divergence: \nabla \cdot \mathbf{F} (LaTeX), div(f) (plain text)
  • Curl: \nabla \times \mathbf{F} (LaTeX), curl(f) (plain text)
  • Laplacian: \nabla^2 f (LaTeX), laplacian(f) (plain text)
  • Vector notation styles:

- Bold: \mathbf{v} - Arrow: \vec{v} - Hat (unit vectors): \hat{n}

Set Theory

  • Operations: \cup (union), \cap (intersection), \setminus (difference)
  • Relations: \in, \notin, \subset, \subseteq, \supset, \supseteq
  • Special sets: \emptyset or \varnothing (empty set)
  • Number sets: \mathbb{N}, \mathbb{Z}, \mathbb{Q}, \mathbb{R}, \mathbb{C}, \mathbb{H} (quaternions)
  • Power set: \mathcal{P}(A)
  • Quantifiers: \forall (for all), \exists (there exists)

Logic

  • Connectives: \land (and), \lor (or), \lnot (not)
  • Implications: \implies, \iff (if and only if)

Structures

  • Vectors: \begin{pmatrix} a \\ b \end{pmatrix}
  • Matrices: \begin{bmatrix} a & b \\ c & d \end{bmatrix}
  • Equations: x = y
  • Inequalities: x < y, \leq, \geq, \neq

Advanced Examples

Vector Calculus

use mathlex::parse_latex;

// Maxwell's equations components
let gauss = parse_latex(r"\nabla \cdot \mathbf{E}").unwrap();
let faraday = parse_latex(r"\nabla \times \mathbf{E}").unwrap();

// Laplacian operator
let poisson = parse_latex(r"\nabla^2 \phi").unwrap();

// Vector identities
let div_curl = parse_latex(r"\nabla \cdot (\nabla \times \mathbf{F})").unwrap();
let curl_grad = parse_latex(r"\nabla \times (\nabla f)").unwrap();

Multiple Integrals

use mathlex::parse_latex;

// Surface area integral
let surface = parse_latex(r"\iint_R f(x,y) dA").unwrap();

// Volume integral
let volume = parse_latex(r"\iiint_V \rho dV").unwrap();

// Closed line integral (circulation)
let circulation = parse_latex(r"\oint_C \mathbf{F} \cdot d\mathbf{r}").unwrap();

Set Theory and Logic

use mathlex::parse_latex;

// Set operations
let union = parse_latex(r"A \cup B \cap C").unwrap();
let membership = parse_latex(r"x \in A \cup B").unwrap();

// Logical statements
let forall = parse_latex(r"\forall x \in \mathbb{R} (x^2 \geq 0)").unwrap();
let exists = parse_latex(r"\exists x (P(x) \land Q(x))").unwrap();
let implication = parse_latex(r"P \implies Q").unwrap();

Quaternions

use mathlex::{Expression, MathConstant};

// Quaternion basis vectors satisfy:
// i² = j² = k² = ijk = -1
// ij = k, jk = i, ki = j
// ji = -k, kj = -i, ik = -j

let quaternion = Expression::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)),
};

Context-Aware Parsing

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

// 'e' is parsed as Euler's constant
let euler = parse_latex(r"e^x").unwrap();

// 'i' requires explicit marking to be treated as imaginary unit
let complex = parse_latex(r"3 + 4\mathrm{i}").unwrap();

// Quaternion basis vectors (when marked)
let quat = parse_latex(r"\mathbf{i} + \mathbf{j} + \mathbf{k}").unwrap();

Integration with Evaluation Libraries

mathlex does not evaluate expressions, but it produces a well-defined AST that downstream libraries can consume. For Swift consumers such as numerical or CAS frameworks, the AST is accessible as JSON via the toJSON() and toJSONPretty() methods on MathExpression:

import MathLex

let expr = try MathExpression.parse("sin(x)^2 + cos(x)^2")
let json = try expr.toJSON()
// Decode json into your own Decodable types and evaluate

The serde feature must be enabled on the Rust side (it is included in the default XCFramework build).

Design Philosophy

mathlex is a pure parsing library. It converts text to AST and back - nothing more.

  • No evaluation - mathlex does not compute values
  • No simplification - mathlex does not transform expressions
  • No dependencies on consumers - can be used by any library

This design allows different libraries to interpret the AST according to their capabilities:

  • A CAS library can perform symbolic differentiation on Derivative nodes
  • A numerical library can evaluate Function nodes numerically
  • An educational tool can render step-by-step explanations

Optional Features

Rust

[dependencies]
mathlex = { version = "0.3.4", features = ["serde"] }
  • serde - Enable serialization/deserialization of AST types
  • ffi - Enable Swift FFI bindings (for building XCFramework)

Documentation

License

MIT License - see LICENSE for details.

Package Metadata

Repository: ChrisGVE/mathlex

Stars: 1

Forks: 1

Open issues: 0

Default branch: main

Primary language: rust

License: MIT

README: README.md