Skip to content

MathML ingest

Octant accepts Presentation MathML as a second ingest surface alongside LaTeX. Both paths feed into the same translation pipeline: the same normalization, the same type inference, the same Deep emission, and the same provenance tracking. The MathML surface (introduced in the v0.8.0 feature release) exists because many document systems, including OOXML exports, MathJax serializations, and accessibility toolchains, produce MathML rather than LaTeX.

Given a LaTeX formula and its semantically equivalent Presentation MathML encoding, Octant produces structurally identical Deep from both. This invariant is enforced by a round-trip keystone gate in the test suite: every reference pair in the canonical library carries both a .tex and a .mml file, and the gate asserts that their emitted Deep trees are identical after span identifiers are normalized.

If the gate fails, the build fails. There is no "best effort" mode for structural equivalence.

The MathML ingest surface accepts the Presentation MathML elements that correspond to the supported LaTeX subset. The mapping is direct:

MathML elementLaTeX equivalentNotes
<mi>identifier (x, \sigma)Single-letter or Greek name
<mn>numeric literalInteger, decimal, scientific
<mo>operator (+, -, *, /)Infix and prefix
<mfrac>\frac{a}{b}Float-only division applies
<msqrt>\sqrt{x}
<mroot>\sqrt[n]{x}General power fallback
<msup>superscript / exponentPow lowering table applies
<msub>subscriptFlattened name by default
<msubsup>combined sub/superscript
<mrow>groupingTransparent grouping
<mfenced>delimiters (...), [...]
<munderover>\sum_{i=1}^{n}, \prodBig operators

Elements outside this set produce the same clean errors as unsupported LaTeX constructs. The error message names the MathML element and suggests the equivalent LaTeX rewrite recipe from the limitations page.

MathML files use the same % chelis: magic-comment syntax for type declarations. Place them in an XML comment immediately before the <math> element:

<!-- % chelis: x : f32 -->
<!-- % chelis: n : i32 -->
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mn>1</mn>
<mi>n</mi>
</mfrac>
</math>

This emits (app (var div) (lit 1.0) (cast n f32)). The integer divisor n is coerced to f32 because division is float-only (since chelis 0.12.0).

Span identifiers in MathML mode point to byte ranges within the .mml source file. The sidecar manifest (.spans.json) records the element path and character offsets in the same format as LaTeX spans, so downstream tooling does not need to distinguish between the two ingest surfaces. The octant explain subcommand resolves spans from either source format.

Pass a .mml file to any Octant subcommand the same way you pass a .tex file. Octant selects the ingest surface by file extension:

Terminal window
octant translate formula.mml -o formula.deep
octant check formula.mml
octant explain --target eq:bs_002 formula.mml

The --format flag is available if the extension is ambiguous or absent:

Terminal window
octant translate --format mathml input.xml -o output.deep