Foreword
General
This document is the sixth document of the Plurimath specifications series. It specifies pma: the notation Plurimath owns end to end, written for measured quantities and first-class features. Every token is reserved or registry-carried, every form is unambiguous, every error is strict, and nothing is sugar over another parser.
This document is a forward specification: the notation is specified here for implementation, and its first edition as an implemented surface is its first release. Until that release pma carries no compatibility obligation; from it, the surface is editioned and change-controlled like every notation in this series. The grammar is carried by a checksummed artifact generated from the shared registry (clause 13), in the artifact pattern the asciiunits content language established.
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 | The readers and writers per format |
| 1004 | Evaluation | Numeric evaluation of trees |
| 1005 | The AsciiMath notation | The complete AsciiMath surface |
| 1006 | The pma notation | This document: the featureful notation |
Maintainers
This document is maintained by the Plurimath project at https://github.com/plurimath/plurimath.
Introduction
Measured quantities deserve first-class syntax. A metrology author should write (10.3 +/- 0.2) unit(m) and mean exactly that: a value, its uncertainty, its unit — not fight a mathematics notation’s grouping rules, not mark uncertainty through strings, not lose the unit’s quantity kind to positional accident. pma is the notation where that sentence is a program.
AsciiMath (PM 1005) carries the world’s existing linear mathematics, and carries it compatibly — which forbids it from owning its tokens: every extension is a compatibility negotiation. pma starts from the other end. Plurimath owns the grammar, so the reserved words are terminals, +/- is one token, the constructors are atomic, malformed input is a parse error, and there is no fallback-to-letters reading anywhere. The two notations share one registry and one tree; they differ in what they promise. AsciiMath promises compatibility; pma promises precision.
The features that motivated pma are the measured literal, the unit(...) constructor with its quantity assertions, the difference typing of diff(...), and the distribution tags of the uncertainty forms. Every one of them exists in exactly one shape here — the rejected-syntax annex records the shapes that lost, and why, so the decisions stay made.
EXAMPLE
(10.3 +/- 0.2) unit(m) — the canonical measured literal. Expected outcome. one uncertainty node (PM 1002): value 10.3, magnitude 0.2, category standard, unit the metre — materialised in one form, rendered everywhere, readable by evaluation when it arrives.
1 Scope
1.1 General
This document specifies the pma notation:
the design rules the notation is built under;
the grammar surface and its token discipline;
the constructors: unit, ustd, uexp, ucov, diff;
the measured literals and their modifiers;
quantity assertions and the static semantics they invoke;
the rejected syntaxes, and what replaces each;
materialization into the math model and the rendering relationships to AsciiMath;
the artifact and runtime model;
conformance.
This document does not specify: the model the notation materialises into (PM 1001), the uncertainty fields (PM 1002), the evaluation that will consume it (PM 1004), the units grammar behind unit(...) (CalConnect 36817), or the quantity semantics behind the assertions (CalConnect 36815 and 5) — each is referenced where it applies.
1.2 Relationship to the series
| Document | Relationship to this one |
|---|---|
| 1001 Math model | the tree pma materialises into; renderers and the evaluator come free with it |
| 1002 Uncertainty model | the fields the uncertainty constructors carry |
| 1005 The AsciiMath notation | the sibling notation; shares the registry, differs in promises; the rendering relationship of clause 11 |
| CalConnect 36813, 4, 5, 6 | the numeric contract, the quantity kinds, the static semantics, and the unit(...) content grammar |
1.3 Audience
Implementers of pma, authors who will write it, and the maintainers of the registry and the artifacts it generates.
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.
PM 1003 (format interfaces), of this series.
PM 1004 (evaluation), of this series.
PM 1005 (the AsciiMath notation), of this series.
CalConnect 36813 (numeric contract), — the exact-decimal discipline of the values the literals carry.
CalConnect 36815 (units model), — the quantity kinds the assertions name.
CalConnect 36816 (conversions), — the static semantics the assertions invoke.
CalConnect 36817 (asciiunits content language), — the grammar inside unit(...), and the artifact pattern of clause 13.
JCGM 100:2008, INTERNATIONAL ORGANIZATION FOR STANDARDIZATION, ORGANISATION INTERNATIONALE DE NORMALISATION (ISO), INTERNATIONAL ELECTROTECHNICAL COMMISSION, COMMISSION ÉLECTROTECHNIQUE INTERNATIONALE (IEC), INTERNATIONAL ORGANIZATION OF LEGAL METROLOGY, ORGANISATION INTERNATIONALE DE MÉTROLOGIE LÉGALE (OIML), INTERNATIONAL UNION OF PURE AND APPLIED CHEMISTRY, UNION INTERNATIONALE DE CHIMIE PURE ET APPLIQUÉE (IUPAC), INTERNATIONAL UNION OF PURE AND APPLIED PHYSICS, UNION INTERNATIONALE DE PHYSIQUE PURE ET APPLIQUÉE (IUPAP), INTERNATIONAL FEDERATION OF CLINICAL CHEMISTRY AND LABORATORY MEDICINE, FÉDÉRATION INTERNATIONALE DE CHIMIE CLINIQUE ET DE BIOLOGIE MOLÉCULAIRE (IFCC), INTERNATIONAL LABORATORY ACCREDITATION COOPERATION, COOPÉRATION INTERNATIONALE D’ACCRÉDITATION DES LABORATOIRES (ILAC), and BUREAU INTERNATIONAL DES POIDS ET MESURES (BIPM). Guide to the expression of uncertainty in measurement. Report no. JCGM 100:2008. First edition. Paris: International Bureau of Weights and Measures, Bureau international des poids et mesures; International Organization for Standardization, Organisation internationale de normalisation; International Electrotechnical Commission, Commission électrotechnique internationale, 2008. Available from: https://www.bipm.org/documents/20126/2071204/JCGM_100_2008_E.pdf/cb0ef43f-baa5-11cf-3f85-4dcd86f77bd6.
JCGM 101:2008, INTERNATIONAL ORGANIZATION FOR STANDARDIZATION, ORGANISATION INTERNATIONALE DE NORMALISATION (ISO), INTERNATIONAL ELECTROTECHNICAL COMMISSION, COMMISSION ÉLECTROTECHNIQUE INTERNATIONALE (IEC), INTERNATIONAL ORGANIZATION OF LEGAL METROLOGY, ORGANISATION INTERNATIONALE DE MÉTROLOGIE LÉGALE (OIML), INTERNATIONAL UNION OF PURE AND APPLIED CHEMISTRY, UNION INTERNATIONALE DE CHIMIE PURE ET APPLIQUÉE (IUPAC), INTERNATIONAL UNION OF PURE AND APPLIED PHYSICS, UNION INTERNATIONALE DE PHYSIQUE PURE ET APPLIQUÉE (IUPAP), INTERNATIONAL FEDERATION OF CLINICAL CHEMISTRY AND LABORATORY MEDICINE, FÉDÉRATION INTERNATIONALE DE CHIMIE CLINIQUE ET DE BIOLOGIE MOLÉCULAIRE (IFCC), INTERNATIONAL LABORATORY ACCREDITATION COOPERATION, COOPÉRATION INTERNATIONALE D’ACCRÉDITATION DES LABORATOIRES (ILAC), and BUREAU INTERNATIONAL DES POIDS ET MESURES (BIPM). Supplement 1 to the “Guide to the expression of uncertainty in measurement” — Propagation of distributions using a Monte Carlo method. Report no. JCGM 101:2008. First edition. Paris: International Bureau of Weights and Measures, Bureau international des poids et mesures; International Organization for Standardization, Organisation internationale de normalisation; International Electrotechnical Commission, Commission électrotechnique internationale, 2008. Available from: https://www.bipm.org/documents/20126/2071204/JCGM_101_2008_E.pdf/325dcaad-c15a-407c-1105-8b7f322d651c.
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 constructor
a reserved keyword(args) form that materialises as a single model node
3.2 reserved word
a constructor keyword or grammar terminal; the build fails on any collision between a reserved word and the registry’s or the UnitsDB symbol space’s names
3.3 measured literal
the (v +/- u) form with its modifiers: the relative form, the shared exponent, the distribution tag
3.4 trailing unit
a unit(...) following a value or a measured literal, scoping the unit of the whole quantity
3.5 quantity assertion
the :: annotation binding a quantity kind to a unit expression
3.6 distribution tag
the ~name modifier selecting an uncertainty distribution family from the closed JCGM-grounded set
the (v +/- u)eE form, where the exponent shifts the value and the uncertainty together
3.8 relative form
the (v +/- n%) form, where the uncertainty is a percentage of the value
3.9 desugar
the reduction of a literal or sugar form to its canonical constructor shape before materialization
3.10 artifact
the checksummed pma grammar artifact, generated from the shared registry, consumed by every runtime
3.11 strict error
a parse or validation error with no fallback reading; the only failure mode this notation has
4 Conventions
4.1 General
pma text is shown verbatim; the canonical ASCII form is normative and the ± spelling is its fenced sugar. Trees are named in the model terms of PM 1001. The ± character is U+00B1.
4.2 Examples
Examples carry an Expected outcome paragraph. Where an example shows a refusal, the outcome names the error class per PM 1003’s Annex A and the message shape this document fixes.
4.3 Forward-specification status
This document specifies the notation for implementation. Rules stated here are the specification the implementation follows; until first release, an implementation gap is a defect of the implementation against this document, not of the document.
4.4 The artifact references
Where a clause says the grammar carries a form, the artifact is the carrier: this document states the form, the artifact makes it runnable, and the two are checked against each other in the build. References to CalConnect 36817’s grammar are by content, not by copy — the unit grammar appears once, in its own series, and both notations point at it.
5 Design rules
5.1 The six rules
Everything in this notation follows from six rules:
Owned grammar. The reserved words are terminals of the grammar; the grammar is generated from the shared registry, and the artifact is checksummed. Plurimath owns the notation, so there are no shims to write and none to maintain.
Reserved-word safety. The build fails on any collision between a reserved word and any name in the registry’s symbol space or the UnitsDB symbol space. The failure happens at grammar generation — a collision never reaches a parser.
Explicit input. Values are typed explicitly: the constructors and literals carry their fields in their syntax. Reporting conventions — the concise form above all (PM 1002) — are output-only renderings, never input.
Strict errors. A malformed form is a parse error. There is no fallback-to-letters reading, no best-effort interpretation, no load-bearing whitespace trick.
No strings as syntax. The quoted-string channel is an AsciiMath device (PM 1005); this notation has none of it. unit(...) is unquoted — it is a constructor, and it can afford to be.
No conversion syntax. Converting a quantity is an operation evaluation performs (document 1004’s convert), not document syntax. A notation that converts inline is a calculator; pma is a notation.
EXAMPLE
Adding measure as a constructor whose name collides with a UnitsDB symbol. Expected outcome. the build fails at grammar generation with the collision named. The parser never sees a doubled word, and no runtime resolves the ambiguity — because there is no ambiguity to resolve.
5.2 What the rules buy
The rules are why pma errors can be exact. A reader that owns its tokens knows every input is either one of its forms or an error; there is no third case where a spelling might be legacy content. PM 1003’s typed errors become exhaustive here: every refusal names a rule of this document, and every acceptance materialises a tree the model fully defines.
5.3 The rules against the features
Each feature exists because a rule allows it, and each rule kills a class of mistakes:
| Rule | Enables | Kills |
|---|---|---|
| owned grammar | the constructors as terminals | the shim layer |
| reserved-word safety | stable keywords forever | accidental collisions |
| explicit input | the literals and their fields | input-side guessing |
| strict errors | exhaustive error handling | silent misreads |
| no strings as syntax | the unquoted unit(...) | the quoted channel’s limits |
| no conversion syntax | a grammar that stays a grammar | inline semantics creep |
The table is this document in miniature: the clauses that follow are the features, and every one of them sits inside a rule.
6 The grammar
6.1 General
The grammar of pma is stated here in full, in PARG — the grammar language of the asciiunits artifact pattern (CalConnect 36817) — as the normative source the pma artifact generates from. A developer implements the reader from this grammar, the materialization rules of clauses 7 and 8, and nothing else: every input is derivable to exactly one tree, or refused by exactly one error.
The unit expressions inside unit(...) are not re-stated here: the rule references the CalConnect 36817 grammar (the UnitsmlAscii artifact), embedded by reference at compile time — one unit grammar, two notations.
6.2 The grammar
# The pma grammar: arithmetic core, measurement constructors, measured
# literals, quantity assertions. Edition 1. Generated into the pma
# artifact; reserved words are checked against the registry's symbol
# space and the UnitsDB symbol space at generation time.
grammar Pma version "0.1.0" edition 1 {
# lexical terminals
ws = %x09 / %x0A / %x0B / %x0C / %x0D / %x20
spaces = 1*ws
digit = %x30-39
digits = 1*digit
lparen = "("
rparen = ")"
comma = ","
plus = "+"
minus = "-"
star = "*"
slash = "/"
caret = "^"
percent = "%"
e_mark = "e"
tilde = "~"
colon_colon = "::"
plus_slash_minus = "+/-"
plusminus = "±"
equals = "="
not_equals = "!="
lt = "<"
le = "<="
gt = ">"
ge = ">="
number = (["-"] digits ["." digits]) as number
# names: identifiers for evaluation bindings. The name table is
# generated as the identifier shape minus the reserved words — the
# same generation-time subtraction the unit tables use.
letter = %x41-5A / %x61-7A
underscore = "_"
name = (letter 1*(letter / digit / underscore)) as name
# the reserved words: checked against registry ∪ unitsdb at generation
reserved_unit = "unit"
reserved_ustd = "ustd"
reserved_uexp = "uexp"
reserved_ucov = "ucov"
reserved_diff = "diff"
# distribution tags: the closed set
tag_name = ("rect" / "tri" / "u") as distribution
# unit expressions: the CalConnect 36817 grammar, embedded by reference
unit_expression = @UnitsmlAscii.expression
kind_name = from_table "kinds" column "name" as kind
# ---- expressions ----
expression = relation
relation = additive [ (equals / not_equals / lt / le / gt / ge) additive ]
additive = multiplicative 1*((plus / minus) multiplicative)
multiplicative = unary 1*((star / slash / keyword_mod) unary)
keyword_mod = "mod"
unary = [plus / minus] power
power = primary [caret unary]
primary = number / literal / constructor_call / name / (lparen expression rparen)
# ---- measured literals ----
literal = lparen number plus_slash_minus magnitude rparen [exponent] [tag] [trailing_unit] as literal
literal_sugar = lparen number plusminus magnitude rparen [exponent] [tag] [trailing_unit] as literal
magnitude = (number [percent]) as magnitude
exponent = e_mark ["-"] digits as exponent
tag = tilde tag_name as tag
# ---- constructors ----
constructor_call = ustd_call / uexp_call / ucov_call / diff_call / unit_call
ustd_call = reserved_ustd lparen number comma [spaces] number rparen [trailing_unit]
uexp_call = reserved_uexp lparen number comma [spaces] number comma [spaces] number [comma [spaces] number] rparen [trailing_unit]
ucov_call = reserved_ucov lparen number comma [spaces] number comma [spaces] number [comma [spaces] number] comma [spaces] kind_name rparen [trailing_unit]
diff_call = reserved_diff lparen expression rparen
unit_call = reserved_unit lparen unit_expression [colon_colon kind_name] rparen
trailing_unit = unit_call
# ---- entry ----
entry pma: expression
test pma {
accept "(10.3 +/- 0.2) unit(m)"
accept "(10.3 +/- 2%) unit(m)"
accept "(3.85 +/- 0.23)e4 unit(m)"
accept "(0.5 +/- 0.01) ~rect unit(m)"
accept "(10.3 ± 0.2) unit(m)"
accept "ustd(10.3, 0.2) unit(m)"
accept "uexp(10.0, 0.3, 2, 0.95) unit(cm)"
accept "ucov(10.0, 9.7, 10.3, 0.95, shortest) unit(cm)"
accept "ucov(10.0, 9.7, 10.3, probabilistically-symmetric)"
accept "unit(kg m/s^2)"
accept "unit(Bq)::frequency"
accept "diff(5 unit(degC))"
accept "x^2 + 1"
accept "2 * (3 + 4)"
reject "10.3(2)"
reject "3+-1"
reject "10.3 +/- 0.2"
reject "(0.5 +/- 0.01) ~magic"
reject "2x"
reject "\"unitsml(g)\""
}
}
6.3 Reading the grammar
The repetition, option and alternative operators are PARG’s (1*, [...], ordered /), as in the asciiunits artifact; the ordered choice makes the alternative order decisive, exactly as it is there.
The as captures name the tree positions the materializer consumes: number, name, literal, magnitude, exponent, distribution, kind.
The name rule’s table is generated as the identifier shape minus the reserved words — the generation-time subtraction, the same discipline the unit tables use, so a reserved word can never read as a name.
@UnitsmlAscii.expression embeds the CalConnect 36817 grammar by reference at compile time; the unit expressions carry that grammar’s captures into the tree under the unit node.
The test block is normative: the artifact’s conformance runs the accepts and rejects on every build, and this document’s vectors extend them.
6.4 What the grammar deliberately lacks
No quoted strings. There is no double-quote token; a quote anywhere is a lexical error (clause 10).
No implicit multiplication. Adjacency is not an operator: 2x does not derive, and the test block rejects it. Multiplication is written *.
No comments. A pma input is one expression; there is nothing to comment.
No statement terminators or sequences. Edition 1’s input is one expression; sequences are an edition’s addition, with their separator.
No subscript. The _ token does not exist; ^ is the power operator only.
6.5 The tree, in one table
What each derivation yields, for the materializer:
| Production | Captures consumed | Node materialised |
|---|---|---|
| literal | number, magnitude, exponent, distribution, trailing unit | the desugared uncertainty record (clause 8) |
| ustd_call, uexp_call, ucov_call | the number captures, the kind | the uncertainty record per PM 1002 |
| unit_call | the unit expression, the kind | the Unitsml node, assertion recorded |
| diff_call | the operand expression | the difference-typed quantity (clause 12) |
| number, name | the text | Number, the binding name |
| the operators | the folded operands | the model’s operators (PM 1004’s chain) |
6.6 Completeness, stated
The grammar derives every input this document’s clauses describe and nothing else. A form the clauses describe but the grammar does not derive is a defect in one of the two; a form the grammar derives but no clause describes is likewise. The test block, the vectors of Annex E, and the clause cross-checks are the mechanics of that statement — the statement itself is the standard this document is held to.
7 The constructors
7.1 General
A constructor is atomic: keyword(args) with the argument list its table fixes, materialising one node. A malformed argument list is a parse error — there is no partial record, no default-filled form, no interpretation of what the author probably meant.
7.2 unit
unit(<expression>) carries one unit expression in the CalConnect 36817 grammar and materialises a Unitsml node (PM 1001). Alone it states a unit; following a value or a literal it scopes the unit of the whole quantity (the trailing-unit rule below).
7.3 ustd, uexp, ucov
The uncertainty constructors carry PM 1002’s categories with their argument orders:
| Constructor | Arguments in order | Materialises |
|---|---|---|
| ustd(v, m) | value, magnitude | the standard category, notation absolute |
| uexp(v, m, k, p?) | value, magnitude, factor, optional probability | the expanded category |
| ucov(v, l, u, p?, kind) | value, endpoints, optional probability, kind | the coverage-interval category |
Optional arguments are omitted without empty positions, as in AsciiMath. The kinds are shortest and probabilistically-symmetric — the full model names; AsciiMath’s symmetric respelling does not exist here, because this notation owns its tokens and has no minus-sign ambiguity to dodge.
The constructors validate through PM 1002’s rules at materialisation: field rules per category, the positive factor, the bounded probability, the exact decimals. A violation is a construction error naming the field — the same typed refusal the model defines, surfaced at parse time.
7.4 diff
diff(<quantity>) materialises its operand as a difference-typed quantity: the node structure of the operand with the difference typing of the quantity algebra (clause 12). The name diff is the register’s current choice; the register is the place a successor spelling (delta) would land, through the reserved-word process, never by overloading.
7.5 The trailing-unit rule
A unit(...) following a value or a measured literal scopes the unit of the entire quantity, uncertainty included: ustd(10.3, 0.2) unit(m) states a value of 10.3 m with a magnitude of 0.2 m — the magnitude is a difference in that unit (clause 12). The unit is stated once; nothing in the form repeats it per field.
EXAMPLE 1
ustd(10.3, 0.2) unit(m). Expected outcome. one Uncertainty node — value 10.3, magnitude 0.2, category standard, unit the metre. ustd(10.3) is a parse error naming the missing magnitude, not a record with a zero.
EXAMPLE 2
unit(kg m/s^2). Expected outcome. the Unitsml node of the newton’s unit expression — the CalConnect 36817 grammar’s reading, one grammar for both notations.
7.6 The constructors against PM 1002’s rules
The uncertainty constructors do not restate PM 1002’s validation — they invoke it. The table maps each constructor’s refusal to the rule that refuses it:
| Constructor fault | PM 1002 rule invoked | Error shape |
|---|---|---|
| ustd(10.3) — missing magnitude | the standard category requires the magnitude | construction error: “magnitude is required for a standard uncertainty” |
| uexp(10.3, 0.5, 0) — zero factor | the factor must be greater than zero | construction error naming the factor |
| uexp(10.3, 0.5, 2, 1) — probability one | the probability is strictly inside (0, 1) | construction error naming the probability |
| ucov(..., fastest) — unknown kind | the kinds are shortest and probabilistically-symmetric | parse error naming the kind |
| diff(x) — a name, not a quantity | the operand must carry a quantity expression | parse error naming the operand |
The error shapes are this document’s, the rules are PM 1002’s, and the split is deliberate: one model, one validation, two notations surfacing it.
7.7 The trailing unit’s scope, precisely
ustd(10.3, 0.2) unit(m) — the unit scopes the value and the magnitude. uexp(10.0, 0.3, 2, 0.95) unit(cm) — the unit scopes value, magnitude and the interval the factor describes: everything in the record is centimetres. A form with two trailing units is a parse error: the scope is the whole quantity, stated once. A constructor whose operand already carries a unit takes no trailing unit — the scope is decided at the innermost statement, and re-stating it outside is ambiguous about what it would override.
7.8 The unit expression’s strictness
The expression inside unit(...) is the CalConnect 36817 grammar, and its strictness is that grammar’s: an expression the unit reader refuses is a parse error here naming the expression and the unit reader’s message. The channel-less design pays here — in AsciiMath the channel’s content was quoted data; here it is grammar, and the errors are parse errors with positions, not text-channel refusals.
8 Measured literals
8.1 The canonical form
(v +/- u) is the measured literal: value v, uncertainty magnitude u, category standard. +/- is one terminal — the canonical ASCII spelling — and the literal desugars to ustd(v, u) before materialisation. The parenthesised form is the literal’s whole shape; without the parentheses it is not a literal, it is arithmetic.
| Form | Reads as | Desugars to |
|---|---|---|
| (10.3 +/- 0.2) unit(m) | canonical literal with trailing unit | ustd(10.3, 0.2) unit(m) |
| (10.3 +/- 2%) unit(m) | relative: 2 percent of the value | the magnitude computed at materialisation: 0.206, exact per CalConnect 36813 |
| (3.85 +/- 0.23)e4 unit(m) | shared exponent: both shift | ustd(38500, 2300) unit(m) |
| (0.5 +/- 0.01) ~rect unit(m) | distribution tag attached | the standard literal with tag rect |
| (10.3 ± 0.2) unit(m) | the fenced sugar | the canonical literal, identically |
8.2 The relative form
+/- n% states the magnitude as a percentage of the value. The magnitude is computed at materialisation — exactly, per the decimal discipline, never at render or evaluation time — so the tree carries the absolute magnitude and the category, and every surface renders the same record. A percentage that does not produce an exact decimal at the value’s precision is a materialisation error naming both numbers.
8.3 The shared exponent
(3.85 +/- 0.23)e4 shifts value and magnitude by the same exponent: 38500 and 2300. The shift is exact — digit movement, no rounding — and the desugared record carries the shifted decimals. The exponent belongs to the literal, not to the unit: (3.85 +/- 0.23)e4 unit(m) states metres throughout.
8.4 The distribution tag
~name after a literal attaches the distribution family the uncertainty came from: a closed set grounded in the JCGM families (rect for the rectangular, tri for the triangular, u for the normal, and the set’s remaining members as PM 1002’s categories ground them). The tag rides the node as metadata; it changes no arithmetic in this edition, and evaluation (document 1004) will consume it when propagation arrives. A tag outside the closed set is a parse error naming the tag — the set is closed so that consumers can switch on it.
8.5 The ± sugar
(10.3 ± 0.2) is the canonical literal spelled with the fenced ±. It desugars identically; the sugar is fenced-only — the ± appears between the parenthesised literal’s value and magnitude and nowhere else. Outside a fence, ± is not a token of this notation at all: pm names the picometre in unit expressions, and the notation will not overload it.
8.6 What the literals are not
The concise reporting form of PM 1002 is not an input form here (clause 10); the literals carry absolute magnitudes, and the concise rendering of a standard category is a writer’s act. The literal is input-side syntax; the reporting form is output-side convention; the two meet only in the rendering surfaces.
8.7 The literal grammar, precisely
The literal is: (, the value, +/-, the magnitude, ), then in any order at most one shared exponent (e and an integer) and at most one distribution tag (~ and a tag name), then optionally the trailing unit. The relative form replaces the magnitude with an integer-or-decimal and %. Each modifier appears at most once; two exponents or two tags are parse errors. The desugar order is fixed: relative resolution, then the shared exponent shift, then the tag attachment, then the trailing unit — so (3.85 +/- 0.23)e4 and (0.5 +/- 0.01) ~rect compose unambiguously, and (3.85 +/- 0.23)e4 ~rect unit(m) is one literal carrying all three modifiers.
8.8 The desugar table
| Literal | Desugars to | Notes |
|---|---|---|
| (10.3 +/- 0.2) unit(m) | ustd(10.3, 0.2) unit(m) | the canonical case |
| (10.3 +/- 2%) unit(m) | ustd(10.3, 0.206) unit(m) | the exact percentage product |
| (3.85 +/- 0.23)e4 unit(m) | ustd(38500, 2300) unit(m) | the shared shift |
| (0.5 +/- 0.01) ~rect unit(V) | the standard record with tag rect | the tag rides as metadata |
| (10.3 ± 0.2) unit(m) | ustd(10.3, 0.2) unit(m) | the sugar, identically |
8.9 Why the desugar is normative
The desugar is the whole semantics of the sugar: a literal means exactly its desugared constructor shape, and nothing the surfaces do may distinguish a literal from its desugar. The corpus carries each row in both spellings, and a writer that renders the sugar form where the record was written canonically has not misbehaved — the record is the same — but the byte corpus freezes the canonical emission, because the canonical form is what the writer writes.
8.10 Refusals
| Input | Refusal |
|---|---|
| (10.3 +/- ) | parse error: the magnitude is missing |
| (10.3 +/- 2%) unit(m) with a value the percentage turns inexact | materialisation error naming both numbers |
| (3.85 +/- 0.23)e4 e5 | parse error: one exponent at most |
| (0.5 +/- 0.01) ~magic | parse error: the tag set is closed |
| 10.3 +/- 0.2 | parse error: the literal is fenced; bare, the +/- has no literal to belong to |
9 Quantity assertions
9.1 The :: form
A unit expression followed by :: and a kind name asserts the quantity: unit(m/s2)::acceleration states that the expression denotes an acceleration. The kind names are the UnitsDB quantity kinds (CalConnect 36815); the assertion invokes the static semantics of CalConnect 36816 — the expression’s dimension must resolve to the kind’s dimension, and a mismatch is an error at materialisation, not at evaluation time.
9.2 What the assertion is for
The assertion settles what units leave ambiguous: Bq and Hz share a dimension and are different quantities; Sv and Gy likewise. An author who writes unit(Bq)::frequency has said something checkable — and the static semantics check it. An author who writes unit(Bq) without an assertion gets the registry’s primary quantity for the unit (the default), stated so the record is still complete.
9.3 Gating
The strict gating of CalConnect 36816 applies to assertions: an assertion that contradicts the registry’s quantity assignment for the unit refuses, and the refusals the units model defines (becquerel is not a hertz, sievert is not a gray) are materialisation errors here, exactly as they are conversion errors there. The notation does not carry its own quantity logic; it invokes the units model’s.
9.4 Assertions on literals
The trailing unit of a literal carries assertions like any unit expression: (10.3 +/- 0.2) unit(m)::length asserts the metre as a length — redundant with the registry’s default, checked anyway, and stated because the author preferred the record complete.
9.5 The assertion grammar, precisely
The assertion rides a unit expression at the positions a unit expression appears: inside unit(...), and on the trailing unit of a literal or constructor. unit(m/s2)::acceleration, (10.3 +/- 0.2) unit(m)::length, uexp(10.0, 0.3, 2, 0.95) unit(cm)::length — each states the kind of the quantity the unit denotes. An assertion on a bare unit(...) inside an arithmetic product states the product’s operand’s kind, and the static semantics check what the product then builds — the checks are the units model’s, at every position.
9.6 The kinds, named
Kind names are the UnitsDB quantity identifiers in their form: length, acceleration, activity, and the rest of the register. A name the register lacks is a materialisation error naming it — the kinds are data (PM 1001’s registry discipline), and this notation carries no kinds of its own.
9.7 Matched, gated, defaulted
The three assertion outcomes:
| Case | Outcome |
|---|---|
| the kind matches the unit’s dimension and assignment | the assertion is recorded on the node |
| the dimension matches but the assignment is gated (Bq as a frequency, Sv as a gray) | materialisation error naming the gating |
| no assertion written | the registry’s primary quantity for the unit is recorded, stated as the default |
Every outcome leaves the record complete: an author either asserts, or the registry’s default is asserted on their behalf — a tree never carries a unit without a quantity statement.
10 The rejected syntaxes
10.1 General
Every rejected form is recorded with its replacement and its reason. The record is the decision: a proposal to admit one of these forms must argue with the reason, not rediscover it.
10.2 The concise form as input
10.3(2) is not an input form. The shape collides with the notation’s own arithmetic — a number followed by parentheses is multiplication or application territory — and accepting it would make the parser guess between a reported result and a product. The concise form is a reporting convention (PM 1002): writers emit it for the standard category, and the reporting-form reader of AsciiMath (PM 1005) is the input path that exists for it, with its decimal-places rule. pma, which owns its tokens, declines the ambiguity instead.
10.3 +- as the separator
+/- is one token; +- is two characters with a life of their own: 3+-1 is genuinely ambiguous between “three plus minus one” and “three, plus-or-minus one” — the reading the Python uncertainties heritage made famous. This notation resolves it by never offering it: the canonical separator is +/-, and +- is a parse error inside a literal.
10.4 Bare pm and the ± token outside fences
pm is the picometre — a unit token inside unit(...), never a separator. The ± character outside the fenced sugar is not a token: 10.3 ± 0.2 without the parentheses is a parse error, because an unfenced ± invites the same reading ambiguity the fenced form exists to close.
10.5 Conversion syntax
No form of pma converts: (10.3 +/- 0.2) unit(m) -> unit(ft) is not a notation, it is a wish. Conversion is convert(quantity, target) — an operation of evaluation (document 1004), with the conversion law, the exactness rules and the difference typing of the UnitsML series applied where they belong. A notation that converts inline drags those rules into its grammar; pma keeps its grammar a notation.
10.6 Why the record exists
Each rejection is a feature someone will ask for. The annex carries the full rationale (Annex C); this clause carries the rule: the rejected forms stay rejected until an edition argues them back in, with the corpus extended and the rationale answered.
10.7 The rejections at a glance
| Rejected | Replacement | The reason in one line |
|---|---|---|
| 10.3(2) as input | the literal, or the AsciiMath reporting-form reader | the shape is arithmetic territory here |
| +- | +/- | 3+-1 is genuinely ambiguous |
| bare pm as separator | nothing — pm is the picometre | a unit token is never a separator |
| ± outside fences | the fenced sugar | an unfenced ± reopens the reading |
| inline conversion | convert(q, target) at evaluation | the conversion rules live in the units model |
10.8 The one-line rule behind them all
pma separates input syntax from output convention and from evaluation operations, and refuses any form that blurs the lines. The concise form is output; conversion is evaluation; the separator is input and must be unambiguous. Every rejection in this document is one of those lines held.
11 Differences from AsciiMath
This clause is the complete, systematic comparison between pma and the AsciiMath surface of PM 1005. It is organised by category — lexicon, syntax, semantics, errors — and the categories are exhaustive: a construct that is not listed as shared, changed, added, or removed does not exist in either notation’s intersection. A developer implementing pma from this document needs this clause and the grammar of clause 6; nothing else differs.
11.1 Shared, unchanged
These parts of AsciiMath carry into pma with identical syntax and identical meaning:
| Shared | Form | Reference |
|---|---|---|
| numbers | digits with an optional decimal point, exact decimals | clause 6 |
| arithmetic operators | +, -, *, /, ^, mod | clause 6 |
| unary signs | -x, +x | clause 6 |
| grouping | parentheses | clause 6 |
| relations | =, !=, <, <=, >, >= | clause 6 |
| names | identifiers bound at evaluation | clause 6 |
| the power associativity | right-associative ^ | clause 6 |
11.2 Changed
These exist in AsciiMath under one spelling and in pma under another:
| Concept | AsciiMath (PM 1005) | pma | Reason |
|---|---|---|---|
| the unit | the quoted channel "unitsml(...)" | the unquoted constructor unit(...) | no strings as syntax (clause 5) |
| the interval kind probabilistically-symmetric | spelled symmetric | spelled in full | no minus-sign ambiguity to dodge; tokens are owned |
| the uncertainty calls’ context | loose placement rules | strict argument lists with the trailing-unit rule | owned grammar |
| the reserved reading of sum, prod | ternary classes with scripts | reserved words without scripts; iteration bounds are evaluation’s | clause 6’s token discipline |
11.3 Added
These exist only in pma:
| Addition | Form |
|---|---|
| the measured literal | (v +/- u) with its modifiers: relative %, shared exponent e, distribution tag ~name |
| the fenced ± sugar | (v ± u) — fenced only |
| the unit constructor | unit(...) unquoted |
| the difference constructor | diff(...) |
| the quantity assertion | unit-expression :: kind-name |
11.4 Removed — not carried in this edition
AsciiMath’s surface has four areas pma does not carry in this edition, stated so the boundary is exact:
| Area | What AsciiMath has | pma edition 1 |
|---|---|---|
| the mathematical construct surface | frac, root, sqrt, scripts ^/_ on symbols, sum/prod/int with scripts, matrices [[...]], accents, font styles, text(...) | not carried: pma edition 1 is the arithmetic and measurement language; a pma document composes construct content through the model, and an edition may carry a subset later with its grammar and corpus |
| quoted strings | text content and the channel | removed entirely: no quoted-string token exists in pma |
| implicit multiplication | adjacency 2x means 2 * x | removed: multiplication is explicit *; adjacency is a parse error — the owned grammar carries no load-bearing whitespace |
| the reporting form as input | 10.3(2) reads | removed: output-only per clause 10 |
The script tokens ^ and _ in pma belong to the arithmetic’s power operation only: x^2 is the power, and there is no subscript form in edition 1.
11.5 Lexical differences
| Difference | Statement |
|---|---|
| +/- is one token | not + then / then -; the tokeniser’s longest match carries it |
| % is a positional token | only inside a literal’s magnitude position; elsewhere a parse error |
| e in exponent position | only after a literal’s closing parenthesis; elsewhere a name |
| ~ is a positional token | only before a distribution tag; elsewhere a parse error |
| :: is a positional token | only after a unit expression; elsewhere a parse error |
| no quoted-string token | a double quote anywhere is a parse error |
| case sensitivity | identical to AsciiMath: tokens and names are case-sensitive |
11.6 Error differences
Both notations raise PM 1003’s typed errors. The differences: pma’s error set is exhaustive over its grammar (every input is derivable or named by one error — no legacy corner survives to be interpreted leniently), and pma carries no compatibility fallbacks by definition: AsciiMath’s reader honours its baseline’s leniencies where the baseline has them; pma’s reader honours none, because there is no baseline to honour. The practical consequence for implementers: the pma error table of clause 6 is complete, and conformance to it is testable edge to edge.
EXAMPLE
The same intent in both notations — the measured value 10.3 m with standard uncertainty 0.2 m — and the two spellings. Expected outcome. AsciiMath: ustd(10.3, 0.2) "unitsml(m)". pma: (10.3 +/- 0.2) unit(m). Both materialise the same node; the differences clause accounts for every character that differs — the channel became the constructor, and nothing else changed.
11.7 The MECE claim, stated
Every token of pma is either shared, changed, added, or removed by the tables above; every construct is derivable from clause 6’s grammar alone; every input is either derivable — to exactly one tree — or refused by exactly one error. This clause and clause 6 are the whole language; the remaining clauses explain it.
12 Materialization
12.1 One tree
pma materialises into the one math model (PM 1001): the constructors into their nodes, the literals into desugared constructors, the arithmetic into the model’s operators. Nothing about pma survives into the tree — no syntax marker, no provenance flag — because every renderer and the evaluator consume the model, and a tree that remembered its notation would break that for everyone.
The consequence is the system’s economy: pma’s features render to every surface PM 1001 defines with no per-format work beyond the encodings those documents already define. An uncertainty written in pma renders in OMML through PM 1002’s marker convention exactly as one written in AsciiMath does.
12.2 Rendering into AsciiMath
Rendering a pma tree into AsciiMath emits the AsciiMath encodings: the uncertainty calls, the channel for units, the reporting form where the notation carries a concise node. The quoted channel is an AsciiMath device — a pma author never reads their own output through it as input, because pma’s own forms are native; the channel is what the AsciiMath side consumes.
Compatibility relationship. AsciiMath renders into pma natively: the shared tree is pma’s input vocabulary too, and an AsciiMath-read tree writes as pma through the shared constructors. The reverse — pma into AsciiMath — goes through the encodings, and the shared-exponent and tag forms of the literals render into the AsciiMath forms that exist for them.
12.3 The strict error surface
pma’s reader surfaces PM 1003’s typed errors with this document’s rules: parse errors from the grammar, construction errors from the model’s validation, and nothing else. Every error names its clause here. The error corpus of clause 14 freezes the shapes.
12.4 Materialization, worked
(10.3 +/- 0.2) unit(m) + uexp(4.1, 0.3, 2) unit(m):
the literal desugars: ustd(10.3, 0.2) unit(m);
the constructor parses with its arguments and trailing unit;
both materialise: two uncertainty nodes, categories standard and expanded, both metres;
the addition builds over them — syntax, not semantics: the tree states the sum;
rendering: every surface encodes both nodes per PM 1002; evaluation will answer the sum when it can, per its rules.
Expected outcome. a tree that says exactly what was written, in the model’s terms, with the semantics pending in the documents that own them.
12.5 What materialisation refuses
The desugar’s exactness (the relative form’s product), the constructors’ field rules, the assertions’ gating, and the grammar’s strictness — each refusal is a named rule of this document or of PM 1002, at parse or materialisation time, before any tree escapes. A pma reader yields only complete records; the half-built forms the legacy notations tolerated do not exist here because the rules run before the tree does.
12.6 The two notations, side by side
The same measured statement in both notations, and what each promises:
| AsciiMath (PM 1005) | pma (this document) | |
|---|---|---|
| the statement | ustd(10.3, 0.2) "unitsml(m)" | (10.3 +/- 0.2) unit(m) |
| the tree | the uncertainty node | the same node |
| the unit channel | quoted string | the unquoted constructor |
| the tokens | compatibility-negotiated | owned and reserved |
| the errors | strict, with the channel’s limits | strict, exhaustive |
| the promise | the world’s AsciiMath reads unchanged | every token means one thing |
The tree is the shared centre, which is why the table has one identical row: everything below the notation is common. The notations are front doors; the system behind them is one system.
12.7 The rendering relationship, precisely
A pma tree writes to AsciiMath through the encodings: the uncertainty calls, the channel, the reporting form where a concise node exists. The forms pma has that AsciiMath’s writer lacks — the distribution tags, the relative form — render into the encodings AsciiMath has (the tag as its statement, the relative as the computed absolute), because the tree carries the record, not the sugar. An AsciiMath tree writes to pma natively: the constructors are the AsciiMath encodings’ native shapes, and the round trip AsciiMath→tree→pma is lossless by the shared model.
12.8 Migration
The unreleased uncertainty call forms that earlier plurimath work prototyped migrate into pma unchanged in meaning: ustd(v, u) and kin keep their shapes and gain the strict errors, the trailing-unit scoping and the artifact discipline. Nothing released changes — the forms were never released — and the migration note lives here so the history is stated once.
13 Differences and typing
13.1 The difference quantity
diff(5 unit(degC)) materialises a difference-typed quantity: the value five with the unit degree Celsius, typed as a difference — five degrees hotter than something, not five degrees above absolute zero. The typing is the quantity algebra’s (the invariants of the UnitsML series): differences are the values subtraction yields, and they convert factor-only, because offsets do not apply to them.
13.2 Where differences come from
Two roads: the diff(...) constructor states one directly; the subtraction of two absolute quantities of the same unit and quantity kind produces one. Both roads land in the same typing, and the arithmetic gating follows the units model: an absolute and a difference may combine in the ways the invariants define, and the model refuses the rest.
13.3 Why the constructor exists
The subtraction road needs two absolutes to make a difference; an author who starts from “the temperature rose by 5 degrees” has a difference and no base quantity to subtract. diff(...) states it without inventing a base, and the typing carries the statement — so the eventual conversion (diff in kelvin is the same five) and the eventual evaluation see the truth the author stated.
EXAMPLE
diff(5 unit(degC)) converted to the kelvin difference. Expected outcome. 5 K of difference — the factor-only conversion, no offset applied; the typing did its work.
13.4 Differences and the literals
A literal’s magnitude is itself a difference — 0.2 m in (10.3 +/- 0.2) unit(m) is a difference quantity, which is why the trailing unit scopes it and why its conversion is factor-only. The trailing-unit rule and the difference typing meet in every literal: the rule states the unit once because both the value and the difference-in-that-unit share it.
13.5 The invariants, invoked
The quantity algebra’s invariants (the UnitsML series) govern what may combine with what: an absolute plus a difference yields an absolute, a difference plus a difference yields a difference, and the rest refuses. pma states these as materialisation-time checks where the operands are static, and leaves the dynamic cases to evaluation — the notation refuses what it can see, and the evaluator owns what it cannot.
14 Artifacts and runtimes
14.1 The artifact pattern
The pma grammar is carried by a checksummed artifact, generated from the shared registry — the pattern the asciiunits content language established (CalConnect 36817): the grammar source lives with the registry, generation is deterministic, the artifact is committed with its checksum, and consumers verify the checksum before use. Artifact bytes are authoritative; nothing re-derives them at runtime.
14.2 The runtimes
The artifact serves every runtime in the artifact pattern: the Ruby reader first, and the TypeScript runtime from the same artifact. Byte-identical behaviour across runtimes is the pattern’s guarantee — the same artifact, the same parse, the same tree, the same errors — and the corpora of clause 14 pin it cross-runtime as they pin it across versions.
14.3 Editions
The notation is editioned from its first release. Before that release, this document is the specification and the surface may still move; after it, the surface changes only at an edition, per the change discipline of the series: new constructors and literals join through the reserved-word process, the corpus extends, and nothing published changes. The registry’s growth (PM 1001) flows into the unit expressions immediately — the unit grammar is the artifact’s, and its growth is that artifact’s editioning.
14.4 The artifact lifecycle
| Stage | Content |
|---|---|
| source | the grammar source with the registry data it generates from |
| generation | the deterministic build: grammar and tables from the data |
| commit | the artifact and its checksum, committed together |
| consume | runtimes verify the checksum, then read the artifact |
| release | the edition pins the artifact; the corpus freezes against it |
The lifecycle is the asciiunits pattern’s, and its guarantees transfer: the same checksum serves every runtime, a regenerated artifact that differs is a broken build, and the artifact a release names is the artifact forever.
14.5 The TS runtime and the shared corpora
The TypeScript runtime reads the same artifact and replays the same corpora; the cross-runtime class of clause 14 exists to make that a claim rather than a hope. The uncertainty, conversion and conformance sets of the testsuite run on both runtimes and their outputs compare byte for byte — the pattern’s end-to-end statement, checked.
15 Conformance
15.1 General
Conformance to this document is the implementation of the pma reader per clauses 5 to 12, with the artifact discipline of clause 13. The claims follow PM 1003’s shape.
15.2 Conformance classes
| Class | Licenses the implementation to claim | Replay requirements |
|---|---|---|
| read-pma | reads the full surface of clauses 6 to 12, strict errors included | the pma corpus, tree-identical, and the error vectors with their shapes |
| write-pma | writes the canonical surface per this document | the pma column, byte-identical |
| roundtrip-pma | the lossless claim: write, read, equal tree | write-then-read per corpus entry |
| cross-runtime | the same behaviour as the reference runtimes | the shared corpora replayed on the implementation’s runtime |
15.3 The corpora
pma’s own corpus covers: every constructor with its argument orders and omissions; every literal form and its desugar; every assertion, matching and gated; every rejected form as a refusal vector; the difference forms; and the strict error table. The shared corpora — the uncertainty, conversion and conformance sets of the testsuite — pin the cross-runtime and cross-notation behaviour: a pma-written uncertainty and its AsciiMath-written twin render identically everywhere.
15.4 Claims
A claim names the artifact checksum and the corpus generation. An implementation against a moved artifact is a different claim; the discipline is the series’, and pma’s forward-specification status ends at its first release, when the first generation freezes.
16 Annex A: the constructor reference
| Constructor | Arguments | Materialises | Refusals |
|---|---|---|---|
| unit(e) | one unit expression (CalConnect 36817) | Unitsml node | unreadable expression → parse error naming it |
| ustd(v, m) | value, magnitude | standard uncertainty, absolute | field rules of PM 1002 |
| uexp(v, m, k, p?) | value, magnitude, factor, optional probability | expanded uncertainty | factor ≤ 0, probability outside (0, 1) |
| ucov(v, l, u, p?, kind) | value, endpoints, optional probability, kind | coverage interval | forbidden magnitude/factor present; unknown kind |
| diff(q) | one quantity expression | difference-typed quantity | non-quantity operand |
The optional probability is omitted without an empty position, as in AsciiMath. Every refusal names its field and its rule; the message shapes are this document’s and are frozen in the error corpus.
16.1 The constructors’ composition
Constructors compose through the arithmetic: uexp(10.0, 0.3, 2, 0.95) unit(cm) + uexp(4.1, 0.2, 2) unit(cm) is an addition of two expanded uncertainties — valid syntax, materialised nodes, and an evaluation question (document 1004) rather than a notation question. The notation carries what the author stated; the evaluator answers what it means.
17 Annex B: the reserved-word register
17.1 The register at this edition
| Word | Role | Since |
|---|---|---|
| unit | the unit constructor | edition 1 |
| ustd | standard uncertainty | edition 1 |
| uexp | expanded uncertainty | edition 1 |
| ucov | coverage interval | edition 1 |
| diff | difference constructor | edition 1 |
| rect, tri, u | distribution tags | edition 1 |
17.2 The process
A reserved word joins the register through proposal, collision check, and edition: the collision check runs against the registry’s symbol space and the UnitsDB symbol space, and the word joins only if both are clean. The check is the build’s, not a reviewer’s memory. A word never leaves the register (editioned surfaces do not shrink), and a word’s role never changes — a new role is a new word.
17.3 Why the register is small
Six words and three tags is the whole surface, because pma’s features are composable rather than enumerable: the literals desugar to the constructors, the assertions ride the unit expressions, and the arithmetic is the model’s. A notation that needed a keyword per feature would be a command language; this one is a notation.
18 Annex C: the rejected forms, argued
18.1 The concise form
The argument for accepting 10.3(2) as input: authors have results in that shape from reports, and re-typing them is friction. The argument against: the shape is the notation’s own application/multiplication territory, and the input that accepts it must choose between a reported result and a product on syntax that does not distinguish them. The resolution: the reporting form is an output convention of PM 1002 everywhere, and its input path exists where the ambiguity is resolvable — the AsciiMath reader, whose positional rule recovers the magnitude exactly. pma authors convert reported results once, into (10.3 +/- 0.2), and the conversion is data entry, not notation.
18.2 +-
One character of separation, and the reading collapses: 3+-1 is either 3 + (−1) or the literal. The uncertainties heritage chose the literal; the notation chooses the operators, because 3 + (-1) is already unambiguous and the literal already has a spelling. Two spellings for one form is the ambiguity budget spent twice.
18.3 Bare pm
pm is the picometre. A unit-bearing notation that also makes pm a separator has unit(5 pm) meaning two things, and the resolution cannot be syntactic. The ± character keeps the same rule outside fences: it appears exactly where the fence closes it, and nowhere else.
18.4 Conversion syntax
The arrow forms are attractive and wrong here: conversion carries exactness rules, difference typing and quantity gating — whole clauses of the UnitsML series. Inline conversion syntax would restate them as grammar, in a place the grammar cannot check. convert(q, target) is where those rules live; the notation stays a notation.
18.5 The general principle
A rejected form returns through an edition, with its corpus and its rationale answered — not through a reader that accepts it quietly. The refusals are the notation’s promises as much as its acceptances.
19 Annex D: worked examples
19.1 A measurement statement
(10.3 +/- 0.2) unit(m) — the canonical literal with its trailing unit.
the literal desugars to ustd(10.3, 0.2);
the trailing unit scopes both fields;
materialisation: one uncertainty node, category standard, value 10.3, magnitude 0.2, unit the metre.
Expected outcome. rendered to AsciiMath: ustd(10.3, 0.2) "unitsml(m)"; to LaTeX: 10.3(0.2) m; to every surface per PM 1002 — one statement, six encodings, no per-format authorship.
19.2 A relative statement
(5.0 +/- 1%) unit(V) — one percent of five volts.
the relative magnitude computes at materialisation: exact decimal 0.05;
the record is the absolute form.
Expected outcome. the tree carries magnitude 0.05; the surfaces render 5.0(0.05) V shapes; nothing recomputes the percentage at render or evaluation time.
19.3 A shared-exponent statement
(3.85 +/- 0.23)e4 unit(m).
the exponent shifts both: 38500 and 2300, digit movement only;
the desugared record is ustd(38500, 2300) unit(m).
Expected outcome. the exact decimals of the shifted form; no rounding anywhere in the shift.
19.4 A tagged statement
(0.5 +/- 0.01) ~rect unit(V).
the tag attaches to the literal: the uncertainty’s distribution family is the rectangular;
the node carries the tag as metadata; arithmetic is unchanged in this edition.
Expected outcome. the tree with the tag; the surfaces render the tag where their encoding carries it (per PM 1002’s statements) and drop it as presentation where they do not.
19.5 An asserted unit
unit(Bq)::frequency.
the assertion names the kind; the static semantics check the dimension;
the registry’s assignment for Bq is the becquerel’s own quantity — and the gating refuses the frequency claim.
Expected outcome. a materialisation error naming the gating: the becquerel is not a hertz, and the assertion said it was. unit(Bq)::activity — the kind the registry assigns — materialises with the assertion recorded.
19.6 A difference
diff(5 unit(degC)) — the temperature rise.
the constructor types the quantity as a difference;
the conversion to a kelvin difference is factor-only: 5 K of difference, no offset.
Expected outcome. the typed difference; the arithmetic that combines it with absolutes follows the invariants; the evaluation that converts it applies no offset — the typing carried the truth the author stated.
20 Annex E: test-suite examples
Vectors illustrative of the conformance classes of clause 14; the pma corpus freezes them.
20.1 Constructor vectors (class read-pma)
EXAMPLE 1
unit(kg m/s^2). Expected outcome. the Unitsml node of the newton expression; the unit reader’s exact reading, positions preserved for errors.
EXAMPLE 2
ustd(10.3, 0.2) unit(m) and uexp(10.0, 0.3, 2, 0.95) unit(cm) and ucov(10.0, 9.7, 10.3, 0.95, shortest) unit(cm). Expected outcome. the three categories with their fields per PM 1002; the trailing units scoped to the whole quantities.
EXAMPLE 3
ucov(10.0, 9.7, 10.3, probabilistically-symmetric). Expected outcome. the interval without probability, the full kind name — AsciiMath’s symmetric respelling does not exist here.
EXAMPLE 4
diff(5 unit(degC)). Expected outcome. the difference-typed quantity; factor-only conversion to the kelvin difference per clause 12.
20.2 Literal vectors (class read-pma)
EXAMPLE 1
Every form of clause 8’s desugar table, read and compared to its desugar. Expected outcome. equal trees between each literal and its desugared constructor shape — the desugar is normative and tested.
EXAMPLE 2
(10.3 +/- 2%) unit(m). Expected outcome. the exact magnitude 0.206; a percentage that produced an inexact decimal would refuse at materialisation instead.
EXAMPLE 3
(3.85 +/- 0.23)e4 ~rect unit(m). Expected outcome. one literal carrying both modifiers — the exponent shifted, the tag attached.
20.3 Refusal vectors (class read-pma)
EXAMPLE 1
Every row of clause 8’s refusal table and clause 7’s refusal table. Expected outcome. the named error with its message shape — the strict error surface, one vector per rule.
EXAMPLE 2
10.3(2). Expected outcome. a parse error: the reporting form is not an input form of this notation (clause 10).
EXAMPLE 3
3+-1 inside a literal position. Expected outcome. a parse error naming the separator; the canonical +/- is one token and +- is not it.
20.4 Assertion vectors (class read-pma)
EXAMPLE 1
unit(m)::length and unit(Bq)::activity. Expected outcome. recorded assertions — matched and defaulted-and-stated, both complete records.
EXAMPLE 2
unit(Bq)::frequency. Expected outcome. the gating refusal naming the quantity conflict.
20.5 Round-trip and cross-runtime vectors (classes roundtrip-pma, cross-runtime)
EXAMPLE 1
A tree carrying every constructor and literal form, written and read back. Expected outcome. an equal tree; the canonical form re-emitted byte-identically.
EXAMPLE 2
The shared corpora replayed on the TypeScript runtime against the Ruby reference. Expected outcome. byte-identical outputs — the cross-runtime claim, discharged.
Bibliography
[1] Plurimath repository, — https://github.com/plurimath/plurimath
[2] PM 1001, of this series
[3] PM 1002, of this series
[4] PM 1003, of this series
[5] PM 1004, of this series
[6] PM 1005, of this series
[7] CalConnect 36813, of the UnitsML series
[8] CalConnect 36814, of the UnitsML series
[9] CalConnect 36815, of the UnitsML series
[10] CalConnect 36816, of the UnitsML series
[11] JCGM 100:2008, INTERNATIONAL ORGANIZATION FOR STANDARDIZATION, ORGANISATION INTERNATIONALE DE NORMALISATION (ISO), INTERNATIONAL ELECTROTECHNICAL COMMISSION, COMMISSION ÉLECTROTECHNIQUE INTERNATIONALE (IEC), INTERNATIONAL ORGANIZATION OF LEGAL METROLOGY, ORGANISATION INTERNATIONALE DE MÉTROLOGIE LÉGALE (OIML), INTERNATIONAL UNION OF PURE AND APPLIED CHEMISTRY, UNION INTERNATIONALE DE CHIMIE PURE ET APPLIQUÉE (IUPAC), INTERNATIONAL UNION OF PURE AND APPLIED PHYSICS, UNION INTERNATIONALE DE PHYSIQUE PURE ET APPLIQUÉE (IUPAP), INTERNATIONAL FEDERATION OF CLINICAL CHEMISTRY AND LABORATORY MEDICINE, FÉDÉRATION INTERNATIONALE DE CHIMIE CLINIQUE ET DE BIOLOGIE MOLÉCULAIRE (IFCC), INTERNATIONAL LABORATORY ACCREDITATION COOPERATION, COOPÉRATION INTERNATIONALE D’ACCRÉDITATION DES LABORATOIRES (ILAC), and BUREAU INTERNATIONAL DES POIDS ET MESURES (BIPM). Guide to the expression of uncertainty in measurement. Report no. JCGM 100:2008. First edition. Paris: International Bureau of Weights and Measures, Bureau international des poids et mesures; International Organization for Standardization, Organisation internationale de normalisation; International Electrotechnical Commission, Commission électrotechnique internationale, 2008. Available from: https://www.bipm.org/documents/20126/2071204/JCGM_100_2008_E.pdf/cb0ef43f-baa5-11cf-3f85-4dcd86f77bd6.
[12] JCGM 101:2008, INTERNATIONAL ORGANIZATION FOR STANDARDIZATION, ORGANISATION INTERNATIONALE DE NORMALISATION (ISO), INTERNATIONAL ELECTROTECHNICAL COMMISSION, COMMISSION ÉLECTROTECHNIQUE INTERNATIONALE (IEC), INTERNATIONAL ORGANIZATION OF LEGAL METROLOGY, ORGANISATION INTERNATIONALE DE MÉTROLOGIE LÉGALE (OIML), INTERNATIONAL UNION OF PURE AND APPLIED CHEMISTRY, UNION INTERNATIONALE DE CHIMIE PURE ET APPLIQUÉE (IUPAC), INTERNATIONAL UNION OF PURE AND APPLIED PHYSICS, UNION INTERNATIONALE DE PHYSIQUE PURE ET APPLIQUÉE (IUPAP), INTERNATIONAL FEDERATION OF CLINICAL CHEMISTRY AND LABORATORY MEDICINE, FÉDÉRATION INTERNATIONALE DE CHIMIE CLINIQUE ET DE BIOLOGIE MOLÉCULAIRE (IFCC), INTERNATIONAL LABORATORY ACCREDITATION COOPERATION, COOPÉRATION INTERNATIONALE D’ACCRÉDITATION DES LABORATOIRES (ILAC), and BUREAU INTERNATIONAL DES POIDS ET MESURES (BIPM). Supplement 1 to the “Guide to the expression of uncertainty in measurement” — Propagation of distributions using a Monte Carlo method. Report no. JCGM 101:2008. First edition. Paris: International Bureau of Weights and Measures, Bureau international des poids et mesures; International Organization for Standardization, Organisation internationale de normalisation; International Electrotechnical Commission, Commission électrotechnique internationale, 2008. Available from: https://www.bipm.org/documents/20126/2071204/JCGM_101_2008_E.pdf/325dcaad-c15a-407c-1105-8b7f322d651c.
[13] Python uncertainties package documentation, (the +- precedent, Annex C)
[14] asciiunits, — the artifact pattern this notation’s grammar follows (CalConnect 36817)