Foreword
General
This document is the third document of the Plurimath specifications series. It specifies the format interfaces: the readers that turn text and markup in each supported notation into the formula tree, the writers that turn the tree back out, the error behaviour at each boundary, and the round-trip properties that connect them.
The interfaces described here are implemented in the plurimath gem of the 0.11 series. Where this document and the implementation disagree, the disagreement is a defect in one of the two.
Documents in the series
| Number | Title | Subject |
|---|---|---|
| 1001 | Math model | The formula tree, the node classes, the registry, the rendering surfaces |
| 1002 | Uncertainty model | The uncertainty node, its categories, its encodings |
| 1003 | Format interfaces | This document: the readers and writers per format |
| 1004 | Evaluation | Numeric evaluation and uncertainty propagation |
Maintainers
This document is maintained by the Plurimath project at https://github.com/plurimath/plurimath.
Introduction
The math model of PM 1001 is one tree; the world speaks seven notations. The format interfaces are where the tree meets them: a reader for each input notation — AsciiMath, LaTeX, HTML, MathML, OMML, UnicodeMath and the UnitsML unit-expression content — and a writer for each output surface.
A reader is a total function on well-formed input: it accepts text, validates the type and the options, and yields a tree that satisfies the model of PM 1001 — with the input text preserved on the tree for diagnostics. A writer is a deterministic function from tree to bytes, per the stability rules of PM 1001. Between them stand the error contracts: an implementation never leaks an internal exception across a boundary — every failure is one of the typed errors of Annex A, carrying the input and the format that failed.
This document also fixes which directions read back. AsciiMath, MathML, OMML, LaTeX and UnicodeMath read back to the tree they were written from, with the exceptions enumerated in the round-trip clause; HTML does not read back. Where PM 1002 defines uncertainty encodings, this document defines how they read — the marker is authoritative, the visible shape is regenerated.
EXAMPLE
Plurimath::Math.parse("x^2", :asciimath) yields the power tree of PM 1001’s first example, with input_string equal to x^2. Plurimath::Math.parse("<math><msup>...", :mathml) given malformed MathML raises ParseError — or the specialized error the failure maps to — and never a naked parser exception.
0.1 How to read this document
Clauses 5 to 7 are the interface model and the two contracts; they apply to every format. Clauses 8 to 12 are the formats, each self-contained: its reading rules, its writing rules, its place in the round-trip table. Clause 13 is the image surface, clause 14 the round-trip properties, clause 15 conformance. The annexes carry the error classes, the options and the vectors.
A reader implementing one format needs: clause 6 or 7 for the shared contract, their format’s clause, clause 14 for the round-trip claim, and the corpora.
0.2 One system, seven doors
The interfaces exist so that the number of formats never multiplies the number of implementations. Seven notations, two boundaries, one tree: an implementation of this document writes each reader once and each writer once, and every format pair works.
1 Scope
1.1 General
This document specifies the format interfaces of the Plurimath system:
the interface model: readers and writers as typed boundaries over the formula tree;
the reader contract: accepted types, options, error behaviour, and the guarantees every reader makes about the tree it yields;
the writer contract: entry points, determinism, and the display-style option;
the per-format rules for AsciiMath, MathML, OMML, UnicodeMath, LaTeX and HTML, including how the uncertainty encodings of PM 1002 read;
image rendering through the optional renderer;
round-trip properties and their exceptions;
conformance of an implementation.
This document does not specify:
the grammar of each input notation in the abstract — the accepted surface is what the readers accept, and the writer surfaces are defined in PM 1001 and PM 1002;
the math model itself (PM 1001) or the uncertainty fields (PM 1002);
numeric evaluation (PM 1004).
1.2 Relationship to the series
| Document | Relationship to this one |
|---|---|
| 1001 Math model | defines the tree readers yield and the surfaces writers serve |
| 1002 Uncertainty model | defines the encodings this document specifies reading for |
| 1004 Evaluation | consumes the trees readers yield; not a boundary of this document |
1.3 Audience
Implementers of Plurimath, authors of independent readers or writers that must interoperate with it, and applications embedding the system.
1.4 The interface inventory
| Format | Reader | Writer | Round trip |
|---|---|---|---|
| asciimath | yes | yes | lossless |
| latex | yes | yes | lossless |
| html | yes | yes | display only |
| mathml | yes | yes | lossless |
| omml | yes | yes | lossless |
| unicode | yes | yes | lossless |
| unitsml | yes (unit expressions) | — | — |
| image rendering | — | yes (svg, png, pdf, ps) | — |
Every interface reads or writes the one tree of PM 1001; none of them defines content of its own.
2 Normative references
The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.
PM 1001 (math model), of this series.
PM 1002 (uncertainty model), of this series.
MathML 4, W3C Recommendation — the intent attribute and semantics element as read by the MathML interface.
ECMA-376, Office Open XML File Formats, Part 1 — the DrawingML mathematics the OMML interface reads and writes.
Unicode Technical Report #28, Unicode Support for Mathematics — the linear format the UnicodeMath interface reads and writes.
CalConnect 36817 (asciiunits content language), of the UnitsML series — the content of the quoted channel the AsciiMath interface reads and of the unit embedding.
3 Terms and definitions
For the purposes of this document, the following terms and definitions apply.
For the purposes of this document, the following terms and definitions apply.
3.1 reader
a component that converts text or markup of one accepted type into a formula tree
3.2 writer
a component that converts a formula tree into the bytes of one output surface
3.3 interface
one format’s reader, writer, or pair
3.4 accepted type
one of the type keys the parse entry point validates: asciimath, html, latex, mathml, omml, unicode, unitsml
3.5 input string
the original text a reader received, preserved on the yielded tree for diagnostics
3.6 typed error
one of the error classes of Annex A; the only failures that cross an interface boundary
3.7 locale
the parse option selecting language-specific symbol readings for the localized types
3.8 lossless direction
a reader-writer pair whose composition returns a tree equal to the one rendered
3.9 round trip
render a tree with a writer and read the result back with the same format’s reader
3.10 intent authority
the rule that a marker (intent attribute, marker run, intent wrapper) determines the fields, and the visible shape is regenerated from them
3.11 approximate rendering
a registry entry’s LaTeX rendering that does not carry the construct exactly; recorded with the entry, equal in both directions
3.12 reading corpus
the frozen inputs and their trees, replayed to discharge reading claims
3.13 boundary
the seam between the system and a caller, of which this document defines two: the reader’s and the writer’s
3.14 channel
the quoted UnitsML string of the AsciiMath interface; the reserved form carrying unit expressions
3.15 marker run
the OMML run carrying an uncertainty marker ahead of its construct
3.16 wrapper
the UnicodeMath ⓘ("marker" visible) construct carrying machine-readable intent
3.17 display form
the presentation variant of a surface selected by display style
3.18 corpus generation
a published, immutable version set of the corpora; claims name the generation they were checked against
4 Conventions
4.1 General
Interface signatures are written as parse(text, type, **options) and to_<format>(options) following the implementation’s shape; this document specifies behaviour, not a language binding. Format names follow PM 1001.
4.2 Examples
Examples carry an Expected outcome paragraph stating observable behaviour. Where an example shows reading, the outcome states the resulting tree; where it shows failure, the typed error and its message shape.
4.3 Normative encodings
The encodings read and written here are the ones defined in PM 1001 (surfaces) and PM 1002 (uncertainty); this document adds the reading rules, not new encodings.
4.4 Corpus entries
Where an example says “the corpus freezes” an outcome, the frozen vector is the example with its provenance; the corpora are external, versioned artifacts, and this document’s examples are their illustrations.
5 The interface model
5.1 General
Every exchange with the outside world passes one of two boundaries:
lml "1.0"
models FormatInterfaces {
class Reader {
attribute accepted_type, TypeKey[1]
attribute input, String[1]
attribute options, ParseOptions
}
class Writer {
attribute surface, SurfaceKey[1]
attribute tree, Formula[1]
attribute options, WriteOptions
}
enum TypeKey {
value asciimath
value html
value latex
value mathml
value omml
value unicode
value unitsml
}
enum SurfaceKey {
value asciimath
value html
value latex
value mathml
value omml
value unicodemath
}
class ParseOptions {
attribute locale, String
}
class WriteOptions {
attribute display_style, Boolean
}
}
A reader receives text of one accepted type and yields a formula tree. A writer receives a tree and emits one surface’s bytes. Neither boundary exposes anything else: no parser objects, no intermediate representations, no partial trees.
5.2 The boundaries are typed
Every failure crossing a boundary is a typed error (Annex A). A reader that cannot complete raises a ParseError or one of its specialized subclasses; a writer does not fail on a well-formed tree — render totality is a model guarantee of PM 1001 — and the renderer’s failures are the rendering errors of clause 13.
5.3 Composition
The interfaces compose without glue: the tree a reader yields satisfies every writer. An application may read AsciiMath, inspect the tree, evaluate it (document 1004), and write OMML in one pipeline; no format-specific steps exist between the boundaries.
EXAMPLE
A pipeline that reads LaTeX, writes MathML, reads the MathML back, and writes AsciiMath. Expected outcome. each boundary yields or consumes a tree per this document; the final AsciiMath is a function of the original tree alone, and the intermediate MathML round-trips per clause 14.
5.4 Boundary invariants
Four invariants hold at both boundaries, and the clauses that follow make each precise:
Typed failures. only Annex A’s errors cross; internals stay inside.
Tree guarantees. readers yield PM 1001 trees; writers consume them without inspection of provenance.
No hidden state. a boundary call depends on its arguments and the configuration only — no reader remembers the previous call, no writer caches by identity.
Composition. any reader’s output feeds any writer; nothing between the boundaries knows formats exist.
5.5 Where the units reader sits
The unitsml type is a reader without a writer: it reads one unit expression (CalConnect 36817) into the unit embedding the tree carries. It exists so applications can validate and embed units independently of a surrounding formula, and its failure mode is the parse error naming the unit expression.
5.6 The contracts as obligations
The two boundaries carry symmetrical obligations, which the rest of this document discharges:
| Obligation | Clause |
|---|---|
| validate type and options before work | 6 |
| yield model-conformant trees | 6 |
| preserve the input string | 6 |
| raise only typed errors | 6, Annex A |
| read the encodings of PM 1002 by their authority rules | 8 to 11 |
| Obligation | Clause |
|---|---|
| emit model-defined encodings only | 7 |
| deterministic bytes per model version | 7, PM 1001 |
| totality on well-formed trees | 7, PM 1001 |
| no provenance inspection | 7 |
An implementation audit walks these two tables; the conformance classes of clause 15 are their operational form.
6 The reader contract
6.1 The parse entry point
Reading goes through one entry point, parse(text, type, **options):
The type is validated: an unknown type raises InvalidTypeError, before the text is examined.
The options are validated: only the supported options (locale) are accepted, and an unknown option raises ParseOptionError; a locale passed for a type that does not localize raises the same error naming the type.
The text is parsed by the type’s reader; success yields a formula tree whose input_string is the original text.
Failure raises the specialized error the failure maps to, or ParseError carrying the text and the type.
The entry point never raises any other error. An internal exception escaping a reader is a defect of the reader; the boundary converts everything it can into the typed errors and preserves the specialized ones unchanged.
6.2 Accepted types
| Type | Input | Localized |
|---|---|---|
| asciimath | AsciiMath linear text | yes |
| latex | LaTeX fragment | yes |
| html | HTML fragment | yes |
| mathml | MathML 4 document or fragment | no |
| omml | OMML (DrawingML mathematics) | no |
| unicode | UnicodeMath linear text | yes |
| unitsml | a UnitsML unit expression | no |
The localized types accept the locale option, which selects the language-specific readings of symbols and function names (for instance, localized function names in LaTeX and HTML inputs). The markup types do not localize: a MathML document says what it says.
6.3 The tree guarantee
A reader yields a tree that satisfies PM 1001: node classes from the model, operands in the class-defined order, no formatting in descendant nodes, and — for inputs carrying uncertainty encodings — uncertainty nodes per PM 1002. A reader never yields a tree it cannot itself render.
6.4 The input string
The yielded tree records the input text verbatim. Diagnostics, error messages and the math zone printers may show it; the tree’s identity does not depend on it: two trees read from equal inputs carry the same input_string and are equal; two equal trees from different inputs differ only in that field.
EXAMPLE
Reading "10.3(2)" in AsciiMath. Expected outcome. the tree carries an uncertainty node per PM 1002 (value 10.3, magnitude 0.2, notation concise), and input_string is "10.3(2)".
6.5 Failure
A reader’s refusals are part of its contract. The general ParseError names the input and the type; the specialized errors name their cause: an ambiguous decimal in uncertainty reading raises AmbiguousDecimalError, a missing parsing dependency raises MissingDependencyError. The message shapes of Annex A are stable within an edition.
6.6 Validation order
The entry point validates in a fixed order, so callers can predict which error they see first:
the type — InvalidTypeError before anything else;
the options — ParseOptionError next;
the input — parse errors last.
A call with both an unknown type and an unknown option reports the type. A call with a bad option and a malformed input reports the option. No reader runs before the boundary checks pass.
6.7 What each reader guarantees
Every reader, for every input it accepts, yields a tree with these properties:
the node classes and operand orders of PM 1001;
numbers as exact decimals of the grammar PM 1002 states, wherever the tree carries numbers;
uncertainty nodes constructed through the validation of PM 1002 — a reader never assembles a malformed uncertainty;
units as UnitsML embeddings read from the content language;
no reference to the reader, the type or the options inside the tree.
The last property keeps trees portable: a tree does not remember which reader made it, and PM 1001’s syntax-independence invariant holds at the boundary.
6.8 Reading is not interpretation
Readers translate structure; they do not evaluate, simplify, reorder or repair. An input that says 2 + 2 yields a tree that says 2 + 2; whether that is 4 is evaluation’s business (document 1004). An input with a suspicious construct — a division by a zero-valued expression, an inverted interval — reads as written; the evaluators and the checkers flag, the readers transcribe.
6.9 Reading uncertainty: the summary
The reading rules per format, in one place (the full rules are PM 1002’s encodings plus the clauses above):
| Format | Authoritative channel | Visible shape |
|---|---|---|
| asciimath | the call form / reporting form | is the form |
| mathml | the intent marker | regenerated |
| omml | the marker run | regenerated |
| unicode | the ⓘ marker | regenerated |
| latex | not read | not read |
| html | not read | not read |
A marker and its shape disagreeing is a producer defect; the reader takes the marker, and the next write emits a consistent pair. The corpora include a stale-shape vector per markup format so the authority is tested, not stated.
7 The writer contract
7.1 Entry points
A tree writes to each surface through one entry point: to_asciimath, to_mathml, to_omml, to_latex, to_unicodemath, to_html. The surfaces, their outer elements and their stability rules are PM 1001’s; this document adds the interface obligations.
| Entry point | Obligation this document adds | Reads back |
|---|---|---|
| to_asciimath | emits the call forms and reporting forms that clause 8 reads | yes |
| to_mathml | emits intent markers that clause 9 reads | yes |
| to_omml | emits marker runs that clause 10 reads | yes |
| to_unicodemath | emits the intent wrapper that clause 11 reads | yes |
| to_latex | emits shapes and statements; display surface | no |
| to_html | emits shapes and statements; display surface | no |
7.2 Determinism
Writers are deterministic and byte-stable per PM 1001. This document adds: a writer emits only through its own boundary — no writer depends on a reader having produced the tree, and no writer consults the tree’s input_string.
7.3 The display-style option
The root’s display flag (PM 1001) may be forced per call: a writer asked for display style renders the display form regardless of the root’s flag, and one asked for inline renders inline. Absent an override, the root’s flag decides.
7.4 Failure
A writer given a well-formed tree does not fail. A writer given a tree that violates PM 1001 — an operand missing, an unknown node class — is outside the contract; implementations report it as a programming error, not as a parse or rendering error.
EXAMPLE
The same uncertainty node written to all six surfaces and the outputs collected. Expected outcome. six encodings, one per PM 1002’s tables; byte-identical output on every conforming implementation for each.
7.5 Family obligations per surface
The writers’ family obligations, at the level this document pins them (the per-construct detail is PM 1001’s mapping and PM 1002’s encodings):
| Family | AsciiMath | MathML | OMML | UnicodeMath | LaTeX / HTML |
|---|---|---|---|---|---|
| content | literal | mn/mi/mo/mtext | runs | literal | literal elements |
| structure | linear grouping | mrow families | construct elements | parentheses | nested elements |
| scripts | ^/_ | script elements | script elements | ^/_ | sup/sub, braces |
| fractions | / | mfrac | m:f | / | \frac, layouts |
| nary | name + limits | nary elements | m:nary | symbol + limits | commands + limits |
| tables | [[..]] forms | mtable family | m:m family | ■(...) | environments, tables |
| fonts | call forms | mathvariant | run properties | alphanumeric ranges | font commands, styles |
| uncertainty | calls, reporting form | intent | marker run | wrapper | shapes + statements |
| units | quoted channel | UnitsML form | UnitsML form | ⓐ form | UnitsML form |
Every cell is discharged by the corpora: each family’s row in each surface’s column has corpus vectors, and a writer claim covers its column end to end.
7.6 Writing what was not read
A tree may be built by construction — an application assembling nodes — rather than by reading. Writers treat constructed trees identically: the boundary knows no difference between a read tree and a built one. This is what makes evaluation pipelines possible: document 1004’s output trees write like any others.
7.7 Idempotence of shape
Writing a tree twice yields identical bytes. Writing a read-back tree yields the same bytes as writing the original: the round-trip property plus writer determinism give write-read-write idempotence per lossless format. The corpora assert it.
8 The AsciiMath interface
8.1 Reading
The AsciiMath reader accepts the linear form: symbols and function applications of the registry vocabulary (PM 1001), grouping, scripts, fractions, nary constructions, text in text(...) and in quoted strings, and the uncertainty forms of PM 1002.
The quoted string is content: "unitsml(kg*m/s^2)" is the UnitsML channel, read as a unit embedding; any other quoted string is upright text. The reader does not interpret inside a quoted string beyond the UnitsML channel check.
The uncertainty reading follows PM 1002:
the calls ustd(v, m), uexp(v, m, k, p) and ucov(v, l, u, p, kind) read to their categories with the given fields;
the reporting form v(digits) reads to a standard uncertainty with notation concise and the magnitude reconstructed by the decimal-places rule;
the interval kinds spell shortest and symmetric on input, reading to the model’s kinds;
a malformed form — wrong arity, non-decimal arguments, an unknown kind — is a reading error: AmbiguousDecimalError where the ambiguity is the decimal place count, ParseError otherwise.
8.2 Writing
The AsciiMath writer emits per PM 1002’s encodings: the calls with their argument orders, the concise reporting form for concise nodes, the quoted UnitsML channel for expressible units and the visible unit otherwise.
8.3 Losslessness
The AsciiMath interface is lossless: writing a tree and reading the result yields an equal tree, for every tree the model defines. The one deliberate asymmetry: a concise node writes the reporting form and reads back concise — the notation survives the round trip, as a field of the node.
EXAMPLE
Writing ustd(10.3, 0.2) and reading it back; writing the same node with notation concise and reading that back. Expected outcome. the first round trip returns the node with notation absolute; the second returns notation concise. The two trees differ in that field and in nothing else.
8.4 The accepted surface
The reader accepts the construct families below, in the spellings of the registry vocabulary. The table states each family’s AsciiMath shape and the node it yields; the vocabulary itself is the registry of PM 1001.
8.5 Precedence and grouping
The reader applies the notation’s precedence: scripts bind tighter than adjacency, fractions tighter than addition, and explicit grouping overrides. The tree is the precedence-correct reading; an author who means something else parenthesises. This document does not restate the precedence table — the reader’s behaviour is its definition, and the corpus pins it vector by vector.
8.6 Localization
The localized symbols and function names follow the active locale: an Italian locale reads sen as the sine function where an English reading sees a symbol sequence. Localization affects which tokens map to which nodes; it never changes the tree shape a construct yields.
8.7 Errors and the corpus
The reader’s refusals are pinned by the corpus alongside its successes: every reading error of Annex A that the AsciiMath surface can produce has a corpus vector whose expected outcome is the error and its message shape.
8.8 The quoted channel, precisely
A quoted string in AsciiMath input is content, with exactly one special case: text matching the UnitsML channel shape unitsml(<expression>) becomes a unit embedding. The check is on the whole string, after trimming nothing: " unitsml(g)" with a leading space is text, "unitsml(g)" is the channel. Anything inside the channel that the unit reader refuses is a reading error naming the expression — the channel never silently degrades to text, because a unit intended as a unit must not become prose.
8.9 Concise reconstruction, precisely
On reading the reporting form v(digits):
the value is the text before the parenthesis;
the digit string is the text inside;
the magnitude’s decimal places are the value’s decimal places — the count that made the form well formed;
the magnitude is the digit string with its last digit(s) moved behind a decimal point at that place count, prefixed with 0. when the place count is positive;
the node is constructed with notation concise, through PM 1002’s validation.
A digit string that cannot be reconstructed at the value’s place count — more digits than places is unambiguous, fewer or mismatched is not — raises AmbiguousDecimalError. The reconstruction never invents places: 10(2) reads magnitude 2 at zero places; 10.3(25) refuses.
8.10 Symmetric, precisely
The AsciiMath kind token symmetric reads to probabilistically-symmetric before node construction; the model never sees the short spelling. Writing a probabilistically-symmetric node emits symmetric in AsciiMath and the full name everywhere else. The asymmetry is spell-level and pinned in both corpora.
8.11 AsciiMath error table
| Input fault | Error | Message shape |
|---|---|---|
| unknown token | ParseError | the token and its position |
| arity mismatch in a call | ParseError | the call and its argument count |
| unknown interval kind | ParseError | the kind as written |
| concise place-count mismatch | AmbiguousDecimalError | the value and the digit string |
| refused unit expression in the channel | ParseError | the expression, from the unit reader |
8.12 Writing matrices and alignment
The table classes write in the bracket forms; Align and Eqarray write with the ampersand alignment their reads accept. Alignment points are structural for these classes and survive the round trip; a writer that drops them fails the corpus.
8.13 The vocabulary surface
The AsciiMath reader’s symbol vocabulary is the registry’s AsciiMath token set. The families, with representative tokens (the full set is the registry; the corpus exercises it):
| Family | Representative tokens |
|---|---|
| Greek | alpha, beta, Gamma, Delta, theta, Omega |
| operators | +, -, *, **, times, div, pm, mp, cdot |
| relations | =, !=, <, <=, >, >=, approx, equiv, sim, propto |
| logic and sets | and, or, not, forall, exists, in, notin, subset, cup, cap |
| arrows | ->, =>, <->, iff, mapsto |
| calculus | int, oint, sum, prod, partial, nabla |
| miscellany | oo, emptyset, aleph, hbar, ell, Re, Im, degree |
Function-name tokens follow: sin, cos, tan and kin, log, ln, lg, exp, min, max, gcd, lcm, mod, det, dim, deg, exp, hom, ker, lim with its variants — each reading to its function class. Locale-selected alternatives exist for a number of them, per clause 6.
8.14 Text and quotes, precisely
text(...) reads its content as upright text with grouping; quoted strings read as text with the UnitsML channel exception of this clause. The two forms differ in one observable way: text(...) may contain AsciiMath commands, a quoted string never does — quotes are literal, which is what makes them the right channel for content a formula must not interpret.
8.15 What the corpus pins for AsciiMath
The AsciiMath corpora carry, at minimum: every registry family with a representative per entry-group; every construct family of the table above, in plain and grouped forms; the uncertainty forms of PM 1002 with all categories, notations and kinds; the quoted channel with expressible, inexpressible and refused units; the localization pairs; and the error table’s rows. 143 cases formed the first frozen generation; later generations extend, never rewrite.
9 The MathML interface
9.1 Reading
The MathML reader accepts a MathML 4 document or fragment. It reads the presentation markup into the tree: mi, mn, mo, mrow, mfrac, msqrt, mroot, scripts, tables, and the constructs the model names. Two rules govern semantics:
the intent attribute is authoritative for uncertainty (PM 1002): where an mrow carries an uncertainty marker, the fields come from the marker’s arguments and the row’s visible content is regenerated;
a semantics element carries its annotations as annotation data on the tree, and its first child as the expression.
Unknown presentation elements are read as their content where they are containers and refused where they are not: the reader does not silently drop structure it cannot represent.
9.2 Writing
The MathML writer emits MathML 4 per PM 1001’s surface rules: mathvariant from font styles, intent markers from uncertainty nodes, mtable families from tables, mn/mi/mo per the registry entries. The display attribute follows the root’s flag or the call’s override.
9.3 Losslessness
MathML is lossless for the constructs the model defines, with the intent-authority rule for uncertainty. A MathML document using constructs the model does not define reads to the closest model content it can represent and records nothing else — such documents are outside the losslessness claim.
EXAMPLE
Reading a MathML mrow with intent="expanded-uncertainty(10.3,0.5,2,0.95)" whose visible content shows a stale magnitude. Expected outcome. the tree carries the marker’s fields (0.5, 2, 0.95); the stale visible magnitude is discarded and regenerated on the next write.
9.4 Element mapping
The reader’s element mapping, at family level:
| Element or construct | Node | Notes |
|---|---|---|
| mi, mo with registry entries | Symbol | per the entry’s MathML rendering |
| mn | Number | text verbatim |
| mtext | Text | content verbatim |
| mfrac | Frac | numerator, denominator order |
| msqrt, mroot | Sqrt, Root | degree order preserved |
| msub, msup, msubsup | Base, Power, PowerBase | order preserved |
| munder, mover, munderover | Under, Over, Underover family | per construct |
| nary shapes | the nary classes | character from the construct |
| mtable, mtr, mtd, mlabeledtr | table, Tr, Td, Mlabeledtr | structure preserved |
| menclose, merror, mphantom, mpadded, mspace | the presentation classes | per construct |
| mmultiscripts | Multiscript | pre and post pairs |
| semantics | Semantics | annotations carried |
| intent attribute | per the intent | uncertainty per PM 1002 |
9.5 Whitespace and mspace
Significant whitespace in MathML is structural; the reader treats mspace per its width semantics and collapses presentation-only whitespace, as MathML itself prescribes. Trees carry structure, not spacing.
9.6 Diagnostics
A MathML input that mixes constructs the model cannot represent reads to its representable core; the reading corpora contain such vectors with their expected trees, so the boundary between “reads with loss” and “refuses” is pinned, not folklore.
9.7 Reading algorithm
The MathML reader walks the document in order:
the root element fixes the fragment’s bounds; a stray text outside it refuses;
each element maps per the table of this clause; containers recurse;
intent markers are collected as the elements carrying them close, and the marked element’s node is reconstructed from the marker per PM 1002;
annotations ride with their Semantics node;
the resulting parameters form the tree’s top level, in document order.
9.8 The intent-authority consequence
Because markers are authoritative, a MathML producer has exactly one way to be wrong about uncertainty: emit a marker whose arguments contradict the visible content. That document reads to the marker’s fields. A producer that wants the visible shape to win must not carry a marker; but then the node is not an uncertainty node, and the shape reads as ordinary constructs.
9.9 Entities
Named entities (α) and numeric character references read through the registry’s MathML renderings — an entity the registry knows reads to its entry; an unknown entity is a reading error naming it.
9.10 Writing the intent, concretely
The uncertainty markers of PM 1002 write as the intent attribute value on the enclosing mrow: intent="standard-uncertainty(10.3,0.2)". The attribute is the whole machine-readable contract; a MathML consumer that understands intent reads the fields, one that does not sees the shape. The writer never splits a marker across elements or abbreviates it — the grammar of PM 1002 is the attribute’s entire alphabet.
10 The OMML interface
10.1 Reading
The OMML reader accepts DrawingML mathematics (ECMA-376, m: namespace): runs, run properties, fractions, radicals, scripts, nary constructs, matrices, delimiters, and phantom boxes.
The marker convention is authoritative for uncertainty: a run holding an uncertainty marker string (PM 1002’s grammar) marks the construct that follows; the fields come from the marker and the shape runs are regenerated. A consumer that never learned the convention sees one extra run of text; a conforming reader consumes it.
Run properties map to font styles; m:nary to the nary classes with their character; matrices to the table classes; m:d delimiters to Fenced. As with MathML, structure the model does not define is read to its closest representable content.
10.2 Writing
The OMML writer emits per PM 1001: run properties from font styles, m:nary from nary nodes, m:m matrices with the table class’s delimiters, m:d from fences, and the marker run before the shape runs for uncertainty nodes, with the unit boxed. The display form wraps in m:oMathPara per the root’s flag.
10.3 Losslessness
OMML is lossless for the model’s constructs under the marker-authority rule.
EXAMPLE
Reading an OMML run sequence whose marker run says coverage-interval:shortest(10.3,9.9,10.7,0.95) followed by shape runs showing [9.8, 10.8]. Expected outcome. the tree carries the marker’s endpoints 9.9 and 10.7; the stale shape is discarded; the next write emits the marker’s shape.
10.4 Construct mapping
| Construct | Node | Notes |
|---|---|---|
| m:r runs with m:rPr | Symbol, Number, Text, font styles | properties map to variants |
| m:f with m:num, m:den | Frac | order preserved |
| m:rad | Sqrt, Root | degree hiding per construct |
| m:sSup, m:sSub, m:sSubSup, m:sPre | script classes | pre-scripts to Multiscript |
| m:nary | the nary classes | m:chr carries the character |
| m:d with m:dPr | Fenced | delimiter characters preserved |
| m:m, m:mr, m:eqArr | table classes | delimiters per properties |
| m:box, m:phant, m:groupChr | the presentation classes | per construct |
| marker run | Uncertainty | per PM 1002’s convention |
10.5 The marker run in detail
The marker run is an ordinary m:r whose text matches PM 1002’s marker grammar. The reader scans for it at the start of a construct it marks; on a match, the construct’s fields come from the marker and the shape runs are skipped. A run that resembles a marker but is ordinary text — inside another run, or after the construct it would mark — is text. The convention is positional: marker first, shape after.
10.6 Run properties
Fonts, styles and script positioning in run properties map to the font style nodes and the script placement the model defines; properties without a model counterpart (kerning, colour) are dropped on read, as presentation the tree does not carry.
10.7 Reading algorithm
The OMML reader walks the m: tree:
runs accumulate into content; a marker-matching run switches to marker handling;
construct elements (m:f, m:rad, script and nary elements, m:d, m:m) map per the table;
delimiter and matrix properties select the table class and its fences;
a marker reconstructs the following construct’s uncertainty node per PM 1002 and consumes its shape runs;
document-level properties outside the model are dropped as presentation.
10.8 OMML specificity of the model
Two OMML constructs have model-specific treatment: pre-sub/superscript (m:sPre) reads to Multiscript, and the equation-array constructs read to Align/Eqarray with their alignment. Everything else maps one to one.
10.9 Writing matrices and nary constructs, concretely
The table classes write to m:m with delimiter properties per class: Matrix plain, Pmatrix parenthesised, Bmatrix braced, Vmatrix barred, Cases with the asymmetric brace. The nary classes write to m:nary with m:chr carrying the character and the limits in m:sub/m:sup; a limit absent leaves the element empty rather than omitted, which is how OMML spells “no limit here”.
11 The UnicodeMath interface
11.1 Reading
The UnicodeMath reader accepts the linear format of UTR #28 as the implementation defines its surface: symbols, fractions, scripts, nary constructs, and the intent wrapper ⓘ("marker" visible).
The wrapper is authoritative for uncertainty: the marker string inside the quotes carries the fields; the visible shape inside the wrapper is regenerated. The ⓐ(unit ...) form inside the wrapper carries the unit. Outside wrappers, the linear format reads per its own conventions — ^, _, / grouping, named symbols from the registry’s UnicodeMath tokens.
11.2 Writing
The UnicodeMath writer emits per PM 1001 and PM 1002: the linear forms of the constructs, the intent wrapper for uncertainty nodes with the marker and the regenerated visible shape, and ⓐ(unit ...) for the unit.
11.3 Losslessness
UnicodeMath is lossless for the model’s constructs under the intent-authority rule.
EXAMPLE
Reading ⓘ("standard-uncertainty:concise(10.3,0.2)"10.3(2)). Expected outcome. a standard uncertainty node, notation concise, magnitude 0.2; writing it emits the wrapper again with the reporting form visible.
11.4 Token families
| Family | Shape | Node yielded |
|---|---|---|
| literal characters | Unicode symbol characters | Symbol per registry entry |
| named tokens | alpha, sum, infty | Symbol per entry |
| fractions | a/b, (a+b)/(c+d) | Frac |
| radicals | √x, ∛(x&3) | Sqrt, Root |
| scripts | x^2, x_1 | script classes |
| nary with limits | ∑_(i=1)^n | the nary classes |
| functions | sin, log_2 x | the function classes |
| intent wrapper | ⓘ("marker" visible) | per the marker; uncertainty per PM 1002 |
| units in wrappers | ⓐ(unit ...) | the unit embedding or unit text |
| text | quoted strings | Text |
11.5 The wrapper is the only comment channel
UnicodeMath has no comment or annotation mechanism the model carries; the ⓘ wrapper is the single channel for machine-readable intent. An ⓘ whose quoted text does not match the marker grammar is a reading error, not text — the wrapper is reserved.
11.6 Linear-format precedence
As with AsciiMath, the reader applies the linear format’s precedence and the corpus pins it. Fraction and script grouping in parentheses follows UTR #28’s conventions as the implementation defines them.
11.7 Reading algorithm
The UnicodeMath reader scans the linear text:
literal characters and named tokens read through the registry’s UnicodeMath tokens;
structural characters (/, ^, _, parentheses) build the corresponding nodes;
an ⓘ opens a wrapper: the quoted marker reads per PM 1002’s grammar, the visible shape is skipped or regenerated, and ⓐ inside carries the unit;
a ⓐ outside a wrapper is unit text;
everything else reads per the linear format’s precedence, as the corpus pins.
11.8 Why the wrapper skips and regenerates
The visible shape inside a wrapper was produced from the marker’s fields; re-reading it would invite the stale-shape problem the marker exists to prevent. The reader reads the marker, reconstructs the node, and moves past the visible shape.
12 The LaTeX and HTML interfaces
12.1 LaTeX
The LaTeX reader accepts the fragment-level LaTeX the writer emits, plus the common mathematical core: commands of the registry vocabulary, environments for tables and alignment, and math-mode grouping. It does not accept document preamble, packages or free text outside math.
LaTeX is a lossless direction for the model’s constructs: writing and reading returns an equal tree, with the exceptions the registry records (constructs whose LaTeX rendering is approximate carry the approximation in both directions and are equal as trees).
The LaTeX writer emits per PM 1001 and PM 1002, with the statements of PM 1002 after the unit.
12.2 HTML
HTML is a display surface. The writer emits an HTML fragment optimised for browser presentation: nested elements for structure, sub/sup for scripts, and the encodings of PM 1002 for uncertainty. HTML does not read: the interface has a writer only, and round-trip claims do not include it.
EXAMPLE
Writing the quadratic formula to HTML and to LaTeX. Expected outcome. the HTML fragment renders the same content with presentational markup; the LaTeX fragment is the lossless one; only LaTeX reads back.
12.3 Command mapping
| Command or environment | Node | Notes |
|---|---|---|
| registry commands | Symbol | \alpha, \sum, \infty, and so on |
| digits and . | Number | in math mode |
| \frac{}{}, \tfrac, \dfrac | Frac | style variants to the same node |
| \sqrt{}{}, \sqrt[]{} | Sqrt, Root | optional degree |
| ^{}, _{} | script classes | grouping per braces |
| \sum_{}^{} and kin | the nary classes | limits as given |
| \left..\right | Fenced | delimiter pair preserved |
| matrix, pmatrix, cases, aligned | the table classes | environment per class |
| \text{}, \mbox{}, \mathrm{} | Text, font styles | per command |
| \hat, \bar, \vec and kin | the accent classes | per command |
| \mathbf{} and kin | font styles | per command |
| \textcolor{}{} | Color | colour argument carried |
| uncertainty shapes | Uncertainty | per PM 1002’s LaTeX encodings and statements |
12.4 What the LaTeX reader refuses
Preamble, \usepackage, document environments and free prose between math are refused: the interface is a math fragment interface. A document that carries formulas in prose extracts the formulas first; that extraction is outside this interface.
12.5 The HTML writer’s output shape
The HTML writer emits nested presentational elements: spans for structure, sub/sup for scripts, fraction layouts with borders, tables for matrices, and the statement spans of PM 1002. Class names are stable within an edition and the corpus freezes them.
12.6 An HTML fragment, concretely
The HTML writer’s shape, for the power example of PM 1001:
<span class="plurimath-formula"><i>x</i><sup>2</sup></span>
The class names are the writer’s stable surface: editions may add classes, never rename them. Presentational decisions (fonts, sizes) belong to the host page’s styles; the fragment carries structure and semantics only.
12.7 LaTeX shape, concretely
The same tree in LaTeX:
x^{2}
and the quadratic formula:
x = \left(-b \pm \sqrt{b^{2} - 4ac}\right)/(2a)
The writer emits the linear fraction form when the tree was read from one and the \frac form when built as Frac; both read back to equal trees, and the round-trip corpus carries both shapes.
13 Image rendering
13.1 The renderer
Beyond the text surfaces, a tree renders to images — SVG, PNG, PDF and PostScript — through the optional renderer, which delegates to the lasem library. Rendering goes through one entry point, render(text, type, format:, **options): it parses per clause 6 and renders the parsed tree to the requested image format.
13.2 Availability
Image rendering is available when the lasem gem and its native extension are present; it is never available under Opal. Availability is queryable and never raises: render_available? answers the question, and render raises the typed errors when called without it.
13.3 Failure
The renderer’s failures are typed: RenderingUnavailable when the library is missing, UnsupportedRenderFormat for a format it does not offer, RenderingFailed when rendering fails on a tree that parsed. Parsing failures surface as the parse errors of clause 6 — the renderer never masks a parse failure as a rendering failure.
EXAMPLE
render("x^2", :asciimath, format: :png) with lasem installed. Expected outcome. the PNG of the rendered formula. The same call with lasem absent raises RenderingUnavailable before any parsing work is repeated. A malformed input raises ParseError, not RenderingFailed.
13.4 The rendering pipeline
Rendering composes two boundaries: parse per clause 6, then render the tree to the image format through the library. Options split the same way — parse options to the parse step, the rest to the renderer. The pipeline is one entry point so that callers cannot interleave a broken state: either the image bytes or a typed error, nothing in between.
13.5 Formats and their properties
| Format | Bytes | Notes |
|---|---|---|
| svg | vector | the default |
| png | raster | width options apply |
| vector page | one formula per page | |
| ps | vector page | as pdf |
The corpus freezes one image per format at a reference size; raster differences at other sizes are not drift.
13.6 Availability and platforms
The renderer’s availability follows the library’s platform support: native where the extension builds, absent under Opal and on platforms without the native stack. Applications probe availability once and degrade to text surfaces where images are unavailable; the interface makes degradation explicit rather than failing mid-document.
13.7 Rendering and the model version
Image output depends on the library’s rendering of the intermediate form; it is byte-stable per model version plus library version, and the corpus records both. A library upgrade that changes bytes is a corpus regeneration with provenance, the same discipline as any other byte change.
14 Round trips
14.1 The lossless directions
The lossless directions of the system:
| Format | Round trip | Exceptions |
|---|---|---|
| AsciiMath | yes | none |
| MathML | yes | constructs outside the model |
| OMML | yes | constructs outside the model |
| UnicodeMath | yes | constructs outside the model |
| LaTeX | yes | the registry’s approximate renderings |
| HTML | no | display surface; no reader |
A round trip composes the writer and the reader of one format: read(write(tree)) equals tree, under the structural equality of PM 1001, for trees built from the model’s constructs. The input_string after a round trip is the written form, not the original — identity of trees does not depend on it.
14.2 What survives
Every model field survives every lossless round trip: operands, order, uncertainty categories, fields, notation, interval kinds, units, intent annotations. The encodings of PM 1002 were designed so that no lossless format is the weak link: each carries the marker or the call that reconstructs the node.
14.3 What does not
Three things do not survive, by design and stated here so that no one searches for them:
the original input text (the input_string after a round trip is the written form);
presentation choices that live outside the tree — display style survives, ad-hoc spacing does not;
constructs outside the model, which read to their closest representable content on the way in and therefore cannot survive a round trip unchanged.
EXAMPLE
A tree with a concise uncertainty node round-tripped through AsciiMath, MathML, OMML, UnicodeMath and LaTeX, then read back. Expected outcome. the four lossless round trips each return an equal tree, notation concise everywhere; the LaTeX output is not read back and makes no claim.
14.4 A worked round trip
Start from the tree of Result two of PM 1002’s Annex D: the expanded uncertainty 10.3 g, U = 0.5 g (k = 2, p = 95%).
Write to AsciiMath: uexp(10.3, 0.5, 2, 0.95) "unitsml(g)".
Read it back: the tree, equal, input_string now the written call.
Write to MathML: the intent expanded-uncertainty(10.3,0.5,2,0.95) over the fenced ± shape.
Read that back: the tree, equal again.
Write to LaTeX: (10.3 \pm 0.5) g~(k = 2,~(p = 0.95))-shaped output.
Stop — LaTeX does not read back; the claim ends at the bytes.
Expected outcome. after each lossless leg the tree is equal to the original in every field; the input_string differs at every leg, and identity is unaffected.
14.5 Round trips through different formats
Reading one format’s output with another format is not a round trip; it is two round trips joined by the tree. The composition works because every reader yields model trees and every writer consumes them: AsciiMath in, OMML out, OMML read, HTML out — each boundary checks per its own clause.
14.6 The corpus and the claim
The round-trip corpora freeze, per format: a spread of trees covering every node family, the uncertainty categories, units, and the registry’s approximate-rendering cases. A conforming implementation replays them all; one failure is nonconformance.
15 Conformance
15.1 General
Conformance to this document is claimed per interface class. Every claim is discharged by replaying frozen vectors; nothing here is satisfied by assertion.
15.2 Conformance classes
| Class | Licenses the implementation to claim | Replay requirements |
|---|---|---|
| read-asciimath | reads AsciiMath per clause 8, including the uncertainty reading rules | the AsciiMath reading corpus, tree-identical replay |
| read-mathml | reads MathML per clause 9 | the MathML reading corpus |
| read-omml | reads OMML per clause 10 | the OMML reading corpus |
| read-unicodemath | reads UnicodeMath per clause 11 | the UnicodeMath reading corpus |
| read-latex | reads LaTeX per clause 12 | the LaTeX reading corpus |
| write-<surface> | writes a surface per clause 7 and PM 1001/1002 | the surface column of the render corpus, byte-identically |
| roundtrip-<format> | the lossless claim of clause 14 for a format | the format’s write-then-read corpus |
| render-images | image rendering per clause 13 | the image corpus, byte-identically |
| full-interfaces | all of the above | all corpora |
A read-<format> claim carries the model claim of PM 1001; a roundtrip-<format> claim carries both directions’ claims.
15.3 The corpora
The reading corpora are frozen sets of inputs with frozen trees; the round-trip corpora are frozen trees replayed through write and read. Entries state provenance and never change within an edition.
15.4 Drift
A reader that yields a tree differing from the corpus for the same input does not conform. A writer whose bytes differ from the render corpus does not conform at the corpus’s model version. Drift is resolved by fixing the implementation or moving the model version, and recording which moved.
15.5 Claiming
A conformance claim names its classes, the model version, and the corpus generation. A claim without a corpus generation is not checkable and is not a claim.
15.6 Independent implementations
The contracts are written for more than the reference implementation: an independent reader that yields model trees per clause 6 and passes the reading corpora conforms, whatever its internals. An independent writer that passes the byte corpora conforms, whatever its codegen.
15.7 The error corpus
The typed errors are part of the contract and carry their own vectors: each error class has corpus entries whose expected outcome is the error with its message shape. An implementation that succeeds where the corpus expects a refusal does not conform — refusals are behaviour, not friction.
15.8 Corpus provenance
| Field | Content |
|---|---|
| input or tree | the frozen input text, or the frozen tree for round-trip entries |
| expected | the frozen tree (readers), the frozen bytes (writers), or both (round trips) |
| model version | the version whose behaviour was frozen |
| corpus generation | the generation of the corpus set |
| provenance note | where the entry came from: a clause of this series, a defect fix, a community report |
Claims name the generation they were checked against; a claim against generation N is void for generation N+1 until rechecked. The validator of the register build enforces the naming.
16 Annex A: the typed errors
16.1 General
These are the only errors that cross an interface boundary. Message shapes are stable within an edition; the messages carry the input, the type, or the field responsible.
| Error | Raised by | Means |
|---|---|---|
| InvalidTypeError | parse entry point | the type key is not an accepted type |
| ParseOptionError | parse entry point | an unknown option, or locale for a non-localized type |
| ParseError | any reader | the input cannot be read; carries the text and the type |
| AmbiguousDecimalError | uncertainty reading | a concise form whose decimal places cannot be reconstructed |
| MissingDependencyError | a reader | an optional parsing dependency is absent |
| InvalidUncertainty | uncertainty construction | a field set inconsistent with the category (PM 1002) |
| RenderingUnavailable | renderer | the image library is absent |
| UnsupportedRenderFormat | renderer | the requested image format is not offered |
| RenderingFailed | renderer | rendering failed on a tree that parsed |
Specialized parse errors are subclasses of ParseError: an implementation catching ParseError catches them all, and one catching the subclass catches the specific case.
16.2 What never escapes
Parser internals, XML library exceptions, encoding errors and assertion failures never cross a boundary as themselves: a reader converts them to ParseError with cause information retained for diagnostics. A boundary that leaks a foreign exception is nonconforming.
EXAMPLE
A MathML reader given input that makes the XML library raise. Expected outcome. the caller sees ParseError carrying the input text and the type mathml; the original exception is the cause, not the error.
17 Annex B: options reference
17.1 Parse options
| Option | Applies to | Effect |
|---|---|---|
| locale | asciimath, latex, html, unicode | selects the language-specific readings of symbols and function names |
The locale value follows the implementation’s locale keys. A locale the implementation does not know raises ParseOptionError — silently ignoring a locale would read the wrong language and report success.
17.2 Write options
| Option | Applies to | Effect |
|---|---|---|
| display style | all surfaces | forces the display or inline form regardless of the root’s flag |
17.3 Rendering options
| Option | Applies to | Effect |
|---|---|---|
| format | render | the image format: svg, png, pdf, ps |
| parse options | render | forwarded to the parse step |
Unknown options at any boundary raise the typed option error; no boundary guesses.
17.4 Worked option cases
EXAMPLE 1
parse("\\operatorname{sen} x", :latex, locale: :pt) — a Portuguese input. Expected outcome. with the locale, sen reads as the sine function; the tree is the sine of x. The same call without the locale reads sen per the default vocabulary — a symbol sequence, not the function. The corpora freeze both.
EXAMPLE 2
to_latex(display_style: true) on a tree whose root flag says inline. Expected outcome. the display form; the root’s flag is overridden for this call and unchanged on the tree.
EXAMPLE 3
render("x_1", :asciimath, format: :png) with the library present. Expected outcome. PNG bytes at the reference size; the parse options forward, the rest route to the renderer.
18 Annex C: test-suite examples
Vectors illustrative of the conformance classes of clause 15; the corpora freeze them.
18.1 Reading (classes read-*)
EXAMPLE 1
Reading sum_(i=1)^n i^3 in AsciiMath. Expected outcome. the nary tree of PM 1001’s introduction example, with input_string preserved.
EXAMPLE 2
Reading "unitsml(kg*m/s^2)" inside an AsciiMath formula. Expected outcome. a Unitsml node with the expression kg*m/s^2; the quoted string is the channel, not text.
EXAMPLE 3
Reading an AsciiMath ucov call with kind symmetric. Expected outcome. a coverage-interval node with interval kind probabilistically-symmetric; the AsciiMath spelling maps to the model value.
EXAMPLE 4
Reading 10.3(2). Expected outcome. a standard uncertainty node, notation concise, magnitude 0.2; input_string is 10.3(2).
EXAMPLE 5
Reading a MathML document whose uncertainty mrow carries a stale visible magnitude under an accurate intent marker. Expected outcome. the marker’s fields win; the stale content is discarded.
18.2 Failure (all readers)
EXAMPLE 1
parse("x^2", :fortran). Expected outcome. InvalidTypeError before any parsing.
EXAMPLE 2
parse("x^2", :asciimath, locale: :fr) and parse("<math/>", :mathml, locale: :fr). Expected outcome. the first parses with the French readings; the second raises ParseOptionError naming the type — MathML does not localize.
EXAMPLE 3
parse("ustd(10.3, 0.25, notation: concise)", :asciimath) — wait, that form is not input; the input 10.3(25) with the wrong place count. Expected outcome. AmbiguousDecimalError: the digit string cannot be reconstructed at the value’s decimal places.
EXAMPLE 4
An input that makes the XML library raise inside the MathML reader. Expected outcome. ParseError with the input and type; the foreign exception is the cause.
18.3 Round trips (classes roundtrip-*)
EXAMPLE 1
A tree containing every node family of PM 1001’s Annex A — one construct per class group — round-tripped through AsciiMath, MathML, OMML, UnicodeMath and LaTeX. Expected outcome. five writes, four equal read-backs, and the LaTeX output unread; the HTML column of the same corpus asserts bytes only.
EXAMPLE 2
A concise uncertainty node round-tripped through all four lossless formats. Expected outcome. notation concise after every read-back; the reporting form re-emitted identically each time.
18.4 Image rendering (class render-images)
EXAMPLE
render("x^2", :asciimath, format: :svg) with the library present, then absent. Expected outcome. the SVG bytes frozen in the corpus; then RenderingUnavailable, raised before parsing repeats.
18.5 Boundary behaviour (all classes)
EXAMPLE 1
The same call twice: parse("x^2", :asciimath) then parse("x^2", :asciimath) again. Expected outcome. two equal trees; no state carried between the calls; identical input_string on both.
EXAMPLE 2
A reader yielding to a writer of a different format immediately. Expected outcome. the composition works with no format-specific step; the output is a function of the tree.
EXAMPLE 3
parse called with an option the boundary does not know. Expected outcome. ParseOptionError naming the option; no parsing occurred.
18.6 Localization vectors (localized readers)
EXAMPLE
An AsciiMath input containing a locale-specific function name, read with the matching locale, then with a different one. Expected outcome. the matching locale reads the function node; the other reading treats the token per its own vocabulary — the corpora freeze both outcomes rather than leaving the difference undefined.
18.7 Uncertainty reading vectors (classes read-*)
EXAMPLE 1
An AsciiMath ustd call with three arguments. Expected outcome. a reading error: the standard call takes two; arity errors are ParseError with the input.
EXAMPLE 2
A UnicodeMath ⓘ wrapper whose quoted text is not a marker. Expected outcome. a reading error: the wrapper channel is reserved for markers.
EXAMPLE 3
An OMML sequence whose shape runs precede a marker run. Expected outcome. the marker is positional; a late marker run is text, and the construct reads without uncertainty fields unless another marker precedes it.
18.8 Vocabulary vectors (classes read-asciimath, read-unicodemath, read-latex)
EXAMPLE 1
One representative token per symbol family, read in each linear format. Expected outcome. the same Symbol node per registry entry regardless of format; each format’s token spelling is its own.
EXAMPLE 2
The same expression written with locale-selected function names and read under the matching and the default locale. Expected outcome. the corpora’s frozen pair: function node under the matching locale, symbol-sequence reading under the default — both documented, neither an error.
18.9 Structure vectors (classes read-*)
EXAMPLE 1
A deeply nested expression — a fraction inside a radical inside a script inside a nary limit — read in each markup format. Expected outcome. the same tree shape at every nesting level; no depth-related divergence between readers.
EXAMPLE 2
A table with a labelled row in MathML, read. Expected outcome. a Mlabeledtr in the tree; written to OMML and LaTeX as the labelled row of each surface; round-tripped equal.
18.10 Writer idempotence (classes write-*)
EXAMPLE
Write a tree, read it back, write again — per lossless format. Expected outcome. the second write’s bytes equal the first’s, per format; the corpora assert write-read-write idempotence for every entry.
Bibliography
[1] Plurimath repository, — https://github.com/plurimath/plurimath
[2] PM 1001, of this series
[3] PM 1002, of this series
[4] MathML 4, — https://www.w3.org/TR/MathML4/
[5] ECMA-376, Office Open XML File Formats
[6] Unicode Technical Report #28, Unicode Support for Mathematics
[7] lasem, — the rendering library behind the image surface