Presentation MathML Enhancement
The first part of the up-conversion process takes the rather flat MathML normally output by SnuggleTeX and creates “enhanced” presentation MathML that displays in the same way whilst having a structure that is more amenable to further up-conversion, such as the conversion to Content MathML and Maxima input syntax.
Generally speaking, the enhancements made are as follows:
- Precedence of infix operators is inferred, as described in the table below, using <mrow>...</mrow> to make groupings and delimit inferred arguments.
- Implicit multiplications are inferred, using <mo>⁢</mo> (a.k.a. <mo>⁢</mo> or <mo>⁢</mo>) to represent this in the resulting MathML.
- Applications of pre-defined functions like sin and explicitly assumed functions are inferred, using <mo>⁡</mo> (a.k.a. <mo>⁡</mo> or <mo>⁡</mo>) to represent this.
Precedence Table
The enhancement process works on a list of one or more adjacent MathML element siblings by applying each test in the table below, in the order shown. When the first match occurs, the siblings are mapped into a new form, with the process being repeated in each of the operands.
Test | Result | Live Example |
Infix , | Grouped into a <mfenced> with empty opener and closer and a child for each operand | x,y,z+1 |
Infix ∨ | Associative Grouping | x\vee \lnot y |
Infix ∧ | Associative Grouping | x\vee y \wedge z |
Infix relation operator(s) | Associative Grouping (all at same level) | 1\leq x-a < 2 |
Infix ∪ | Associative Grouping | A\cup B \cap C |
Infix ∩ | Associative Grouping | A\cup B \cap C |
Infix ∖ | Left-associative Grouping | A\setminus B+x |
Infix + | Associative Grouping | x-1+y-2 |
Infix - | Left-associative Grouping | --x-y-z |
Infix *, × and ⋅ | Associative Grouping (all at same level) | 2x+5\times (y-4) |
Infix / and ÷ | Left-associative Grouping | a/b/c/(1 \div x) |
“Space” operators (i.e. anything producing <mspace/>) | Treated as explicit multiplication, grouped associatively | a\,b |
Any infix operator in unary context | Operator “applied” by wrapping in <mrow/> | -+x |
No Infix Operator present | Split into subgroups (as defined below) and apply implicit product | \sin x\cos y |
“Atoms” | Kept, applying conversion process to children | \sqrt{x} |
“No Infix Operator” Handling
Groups of two or more MathML siblings elements that do not contain any infix operators are treated as an implicit product of adjacent sibling subgroups starting with MathML elements satisfying any of the following conditions:
- The first sibling
- The first sibling after an <mfenced/>
- The first of one or more prefix operator or function siblings
- The first non-postfix operator after one or more postfix operator siblings
The handling of these subgroups is described below. The following examples hopefully illuminate this process in more detail:
Grouping Examples
Input | Subgroups | Live Example |
xy | Kept together as one subgroup | xy |
\sin 2x\cos y | Split into \sin 2x and \cos y | \sin 2x\cos y |
\sin f(x) | Treated as \sin (f(x)). (f is assumed to be a function in these examples; this is configurable) | \sin f(x) |
\min(x,y)z | Split into \min(x,y) and z. This demonstrates the rule for handling fences and is appears reasonable here | \min(x,y)z |
\sin(x+1)z | Split into \sin(x+1) and z. This is perhaps contentious, but allows brackets to be used to explicitly delimit function arguments | \sin(x+1)z |
x!y! | Split into x! and y! | x!y! |
\cos x!y! | Split into cos x! and y! | \cos x!y! |
\sin\cos x | Kept together | \sin\cos x |
xy\sin\cos 2ax!y!\min(x,y)a | Split into xy, \sin\cos 2ax!, y!, \min(x,y) and a | xy\sin\cos 2ax!y!\min(x,y)a |
Sibling Subgroup Handling
Once subgroups have been identified (as described above), each of these subgroups is then split into:
- Zero or more prefix operators or unary/n-ary functions
- Zero or more adjacent “atoms”
- Zero or more postfix operators
These are then treated as follows:
-
Any postfix operators are “applied” from right to left to the the atoms before them, using a <mo>⁡</mo> to represent the operator applications.
Note that the factorial operator is handled specially in that it only gets applied to the preceding item, so that 2ax! is treated as 2a(x!), which fits in with common conventions.)
x!!
-
The atoms resulting after applying postfix operators are treated as an implicit multiplication.
Revisiting the 2ax! example, we end up with a product of 2, a and x!.
2ax!
-
Any prefix functions (e.g. \sin) and operators (e.g. \lnot) are “applied” from left to right to whatever is left, using a <mo>⁡</mo> to represent the function applications.
So, \sin\cos 2ax! is handled as it if were \sin(\cos(2ax!)).
\sin\cos 2ax!