mathlex
A mathematical expression parser for LaTeX and plain text notation, producing a language-agnostic Abstract Syntax Tree (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,kbased 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:
[]
= "0.4.0"
Swift
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/ChrisGVE/mathlex.git", from: "0.4.0")
]
Or in Xcode: File → Add Package Dependencies → Enter https://github.com/ChrisGVE/mathlex.git
Quick Start
Rust
Parse Plain Text
use ;
Parse LaTeX
use ;
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
- Standard notation:
- Derivatives (plain text):
- Leibniz:
dy/dx,d2y/dx2,d3y/dx3 - Prime:
y',y'',y''' - Functional:
diff(y, x),diff(y, x, 2)
- Leibniz:
- 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}
- Bold:
Set Theory
- Operations:
\cup(union),\cap(intersection),\setminus(difference) - Relations:
\in,\notin,\subset,\subseteq,\supset,\supseteq - Special sets:
\emptysetor\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 parse_latex;
// Maxwell's equations components
let gauss = parse_latex.unwrap;
let faraday = parse_latex.unwrap;
// Laplacian operator
let poisson = parse_latex.unwrap;
// Vector identities
let div_curl = parse_latex.unwrap;
let curl_grad = parse_latex.unwrap;
Multiple Integrals
use parse_latex;
// Surface area integral
let surface = parse_latex.unwrap;
// Volume integral
let volume = parse_latex.unwrap;
// Closed line integral (circulation)
let circulation = parse_latex.unwrap;
Set Theory and Logic
use parse_latex;
// Set operations
let union = parse_latex.unwrap;
let membership = parse_latex.unwrap;
// Logical statements
let forall = parse_latex.unwrap;
let exists = parse_latex.unwrap;
let implication = parse_latex.unwrap;
Quaternions
use ;
// 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 .into;
Context-Aware Parsing
use ;
// 'e' is parsed as Euler's constant
let euler = parse_latex.unwrap;
// 'i' requires explicit marking to be treated as imaginary unit
let complex = parse_latex.unwrap;
// Quaternion basis vectors (when marked)
let quat = parse_latex.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).
- Wire format reference:
docs/WIRE-FORMAT.md— complete reference for every node type and its JSON representation - Integration example:
examples/numericswift-integration/— SwiftDecodabletypes and a numeric evaluator that consumes the JSON AST
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
Derivativenodes - A numerical library can evaluate
Functionnodes numerically - An educational tool can render step-by-step explanations
Serialization
Enable the serde feature to serialize and deserialize the Expression AST
as JSON:
[]
= { = "0.4.0", = ["serde"] }
use parse;
Every node serializes as { "kind": "<VariantName>", "value": <payload> }.
Each node also carries an AnnotationSet — a string-to-string metadata map
used by downstream consumers such as thales. The annotations field is
omitted when empty, which is always the case for nodes produced directly by
the parsers.
See docs/WIRE-FORMAT.md for the full schema with
one JSON example per variant.
Optional Features
Rust
[]
= { = "0.4.0", = ["serde"] }
serde- Enable serialization/deserialization of AST typesffi- Enable Swift FFI bindings (for building XCFramework)
Documentation
- Rust: docs.rs/mathlex
- Swift: Swift Package Index
License
MIT License - see LICENSE for details.
Links
- Crates.io: crates.io/crates/mathlex
- Swift Package Index: swiftpackageindex.com/ChrisGVE/mathlex
- Documentation: docs.rs/mathlex
- Repository: github.com/ChrisGVE/mathlex
- Issues: Report bugs