|
|
|
@ -1,9 +1,39 @@
|
|
|
|
|
use crate::tokens::Greek;
|
|
|
|
|
use crate::elements::accent::{Color, ExpressionAccent, GenericAccent, OverSet, UnderSet};
|
|
|
|
|
use crate::elements::group::{
|
|
|
|
|
Abs, Angles, Braces, Brackets, Ceil, Floor, Group, Matrix, Norm, Parentheses, Vector, XGroup,
|
|
|
|
|
};
|
|
|
|
|
use crate::elements::literal::{Literal, Number, PlainText, Symbol};
|
|
|
|
|
use crate::elements::special::{
|
|
|
|
|
Expression, Frac, Integral, OIntegral, Pow, Prod, Root, Special, Sqrt, Sub, Sum,
|
|
|
|
|
};
|
|
|
|
|
use crate::elements::Element;
|
|
|
|
|
use crate::tokens::{
|
|
|
|
|
Accent, Arrow, FontCommand, Function, Greek, Logical, Misc, Operation, Relation,
|
|
|
|
|
};
|
|
|
|
|
use htmlescape::{encode_attribute, encode_minimal};
|
|
|
|
|
|
|
|
|
|
pub trait ToMathML {
|
|
|
|
|
fn to_mathml(&self) -> String;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Literal {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
Literal::Text(t) => t.to_mathml(),
|
|
|
|
|
Literal::Symbol(s) => s.to_mathml(),
|
|
|
|
|
Literal::Number(n) => n.to_mathml(),
|
|
|
|
|
Literal::Greek(g) => g.to_mathml(),
|
|
|
|
|
Literal::FontCommand(f) => f.to_mathml(),
|
|
|
|
|
Literal::Relation(r) => r.to_mathml(),
|
|
|
|
|
Literal::Function(f) => f.to_mathml(),
|
|
|
|
|
Literal::Logical(l) => l.to_mathml(),
|
|
|
|
|
Literal::Arrow(a) => a.to_mathml(),
|
|
|
|
|
Literal::Misc(m) => m.to_mathml(),
|
|
|
|
|
Literal::Operation(o) => o.to_mathml(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Greek {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
let inner = match self {
|
|
|
|
@ -48,3 +78,599 @@ impl ToMathML for Greek {
|
|
|
|
|
format!("<mi>{}</mi>", inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for PlainText {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
if let Some(formatting) = &self.formatting {
|
|
|
|
|
format!(
|
|
|
|
|
"<mtext mathvariant='{}'/>{}</mtext>",
|
|
|
|
|
formatting.to_mathml(),
|
|
|
|
|
encode_minimal(self.text.as_str())
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
format!("<mtext/>{}</mtext>", encode_minimal(self.text.as_str()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for FontCommand {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
FontCommand::Big => "bold".to_string(),
|
|
|
|
|
FontCommand::BigOutline => "double-struck".to_string(),
|
|
|
|
|
FontCommand::Cursive => "italic".to_string(),
|
|
|
|
|
FontCommand::TText => "script".to_string(),
|
|
|
|
|
FontCommand::Fr => "bold-fraktur".to_string(),
|
|
|
|
|
FontCommand::SansSerif => "sans-serif".to_string(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Symbol {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!("<mi>{}</mi>", encode_minimal(self.symbol.as_str()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Number {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!("<mn>{}</mn>", encode_minimal(self.number.as_str()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Relation {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
let inner = match self {
|
|
|
|
|
Relation::Eq => "=",
|
|
|
|
|
Relation::Ne => "≠",
|
|
|
|
|
Relation::Lt => "<",
|
|
|
|
|
Relation::Gt => ">",
|
|
|
|
|
Relation::Le => "≤",
|
|
|
|
|
Relation::Ge => "≥",
|
|
|
|
|
Relation::Prec => "≺",
|
|
|
|
|
Relation::Succ => "≻",
|
|
|
|
|
Relation::PrecEq => "≼",
|
|
|
|
|
Relation::SuccEq => "≽",
|
|
|
|
|
Relation::In => "∈",
|
|
|
|
|
Relation::NotIn => "∉",
|
|
|
|
|
Relation::SubSet => "⊂",
|
|
|
|
|
Relation::SupSet => "⊃",
|
|
|
|
|
Relation::SubSetEq => "⊆",
|
|
|
|
|
Relation::SupSetEq => "⊇",
|
|
|
|
|
Relation::Equiv => "≡",
|
|
|
|
|
Relation::Cong => "≅",
|
|
|
|
|
Relation::Approx => "≈",
|
|
|
|
|
Relation::PropTo => "∝",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
format!("<mo>{}</mo>", inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Function {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
let inner = match self {
|
|
|
|
|
Function::Exp => "exp",
|
|
|
|
|
Function::Sin => "sin",
|
|
|
|
|
Function::Max => "max",
|
|
|
|
|
Function::Min => "min",
|
|
|
|
|
Function::Glb => "glb",
|
|
|
|
|
Function::G => "g",
|
|
|
|
|
Function::Lub => "lub",
|
|
|
|
|
Function::Lcm => "lcm",
|
|
|
|
|
Function::Gcd => "gcd",
|
|
|
|
|
Function::Mod => "mod",
|
|
|
|
|
Function::Dim => "dim",
|
|
|
|
|
Function::Det => "det",
|
|
|
|
|
Function::Ln => "ln",
|
|
|
|
|
Function::Log => "log",
|
|
|
|
|
Function::Cot => "cot",
|
|
|
|
|
Function::Csc => "csc",
|
|
|
|
|
Function::Sech => "sech",
|
|
|
|
|
Function::Tanh => "tanh",
|
|
|
|
|
Function::Cosh => "cosh",
|
|
|
|
|
Function::ArcSin => "arcsin",
|
|
|
|
|
Function::ArcCos => "arccos",
|
|
|
|
|
Function::ArcTan => "arctan",
|
|
|
|
|
Function::Tan => "tan",
|
|
|
|
|
Function::Cos => "cos",
|
|
|
|
|
Function::F => "f",
|
|
|
|
|
Function::Sec => "sec",
|
|
|
|
|
Function::Sinh => "sinh",
|
|
|
|
|
Function::Csch => "csch",
|
|
|
|
|
Function::Coth => "coth",
|
|
|
|
|
};
|
|
|
|
|
format!("<mi>{}</mi>", inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Logical {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
let inner = match self {
|
|
|
|
|
Logical::And => "and",
|
|
|
|
|
Logical::Or => "or",
|
|
|
|
|
Logical::Not => "¬",
|
|
|
|
|
Logical::Implies => "⇒",
|
|
|
|
|
Logical::If => "if",
|
|
|
|
|
Logical::Iff => "⇔",
|
|
|
|
|
Logical::ForAll => "∀",
|
|
|
|
|
Logical::Exists => "exists;",
|
|
|
|
|
Logical::Bot => "⊥",
|
|
|
|
|
Logical::Top => "⊤",
|
|
|
|
|
Logical::VDash => "⊢",
|
|
|
|
|
Logical::Models => "⊨",
|
|
|
|
|
};
|
|
|
|
|
format!("<mo>{}</mo>", inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Arrow {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
let inner = match self {
|
|
|
|
|
Arrow::UpArrow => "↑",
|
|
|
|
|
Arrow::DownArrow => "↓",
|
|
|
|
|
Arrow::RightArrow => "→",
|
|
|
|
|
Arrow::To => "→",
|
|
|
|
|
Arrow::RightArrowTail => "↣",
|
|
|
|
|
Arrow::TwoHeadRightArrow => "↠",
|
|
|
|
|
Arrow::TwoHeadRightArrowTail => "⤖",
|
|
|
|
|
Arrow::MapsTo => "↦",
|
|
|
|
|
Arrow::LeftArrow => "←",
|
|
|
|
|
Arrow::LeftRightArrow => "⟷",
|
|
|
|
|
Arrow::BigRightArrow => "⇨",
|
|
|
|
|
Arrow::BigLeftArrow => "⇦",
|
|
|
|
|
Arrow::BigLeftRightArrow => "⬄",
|
|
|
|
|
};
|
|
|
|
|
format!("<mo>{}</mo>", inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Misc {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
let inner = match self {
|
|
|
|
|
Misc::Del => "∂",
|
|
|
|
|
Misc::Grad => "∇",
|
|
|
|
|
Misc::PlusMinus => "±",
|
|
|
|
|
Misc::EmptySet => "∅",
|
|
|
|
|
Misc::Infty => "∞",
|
|
|
|
|
Misc::Aleph => "ℵ",
|
|
|
|
|
Misc::Therefore => "∴",
|
|
|
|
|
Misc::Because => "∵",
|
|
|
|
|
Misc::PLDots => "|…|",
|
|
|
|
|
Misc::PCDots => "|···|",
|
|
|
|
|
Misc::VDots => "︙",
|
|
|
|
|
Misc::DDots => "⋱",
|
|
|
|
|
Misc::EPipes => "||",
|
|
|
|
|
Misc::EQuad => "| |",
|
|
|
|
|
Misc::Angle => "∠",
|
|
|
|
|
Misc::Frown => "⌢",
|
|
|
|
|
Misc::Triangle => "△",
|
|
|
|
|
Misc::Diamond => "⋄",
|
|
|
|
|
Misc::Square => "□",
|
|
|
|
|
Misc::LFloor => "⌊",
|
|
|
|
|
Misc::RFloor => "⌋",
|
|
|
|
|
Misc::LCeiling => "⌈",
|
|
|
|
|
Misc::RCeiling => "⌉",
|
|
|
|
|
Misc::Complex => "ℂ",
|
|
|
|
|
Misc::Natural => "ℕ",
|
|
|
|
|
Misc::Rational => "ℚ",
|
|
|
|
|
Misc::Real => "ℝ",
|
|
|
|
|
Misc::Integer => "ℤ",
|
|
|
|
|
_ => "",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
format!("<mi>{}</mi>", inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Operation {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
let inner = match self {
|
|
|
|
|
Operation::Plus => "+",
|
|
|
|
|
Operation::Minus => "−",
|
|
|
|
|
Operation::CDot => "⋅",
|
|
|
|
|
Operation::Ast => "∗",
|
|
|
|
|
Operation::Star => "⋆",
|
|
|
|
|
Operation::Slash => "/",
|
|
|
|
|
Operation::Backslash => "∖",
|
|
|
|
|
Operation::Times => "×",
|
|
|
|
|
Operation::Div => "÷",
|
|
|
|
|
Operation::LTimes => "⋉",
|
|
|
|
|
Operation::RTimes => "⋊",
|
|
|
|
|
Operation::Bowtie => "⋈",
|
|
|
|
|
Operation::Circ => "∘",
|
|
|
|
|
Operation::OPlus => "⊕",
|
|
|
|
|
Operation::OTimes => "⊗",
|
|
|
|
|
Operation::ODot => "⊙",
|
|
|
|
|
Operation::Wedge => "∧",
|
|
|
|
|
Operation::BidWedge => "⋀",
|
|
|
|
|
Operation::Vee => "∨",
|
|
|
|
|
Operation::BigVee => "⋁",
|
|
|
|
|
Operation::Cap => "∩",
|
|
|
|
|
Operation::BigCap => "⋂",
|
|
|
|
|
Operation::Cup => "∪",
|
|
|
|
|
Operation::BigCup => "⋃",
|
|
|
|
|
_ => "",
|
|
|
|
|
};
|
|
|
|
|
format!("<mo>{}</mo>", inner)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Accent {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
Accent::Hat => "ˆ".to_string(),
|
|
|
|
|
Accent::Overline => "¯".to_string(),
|
|
|
|
|
Accent::Underline => "–".to_string(),
|
|
|
|
|
Accent::Vec => "→".to_string(),
|
|
|
|
|
Accent::Dot => ".".to_string(),
|
|
|
|
|
Accent::DDot => "..".to_string(),
|
|
|
|
|
Accent::UnderBrace => "⏟".to_string(),
|
|
|
|
|
Accent::OverBrace => "⏞".to_string(),
|
|
|
|
|
Accent::Cancel => "⟋".to_string(),
|
|
|
|
|
_ => "".to_string(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for OverSet {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mover accentover='true'><mrow>{}</mrow><mo>{}</mo>",
|
|
|
|
|
self.bottom.to_mathml(),
|
|
|
|
|
self.top.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for UnderSet {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<munder accentunder='true'><mrow>{}</mrow><mo>{}</mo>",
|
|
|
|
|
self.top.to_mathml(),
|
|
|
|
|
self.bottom.to_mathml(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Color {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mstyle mathcolor='{}'>{}</mstyle>",
|
|
|
|
|
encode_attribute(self.color.as_str()),
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for GenericAccent {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self.accent {
|
|
|
|
|
Accent::Hat
|
|
|
|
|
| Accent::Overline
|
|
|
|
|
| Accent::Vec
|
|
|
|
|
| Accent::Dot
|
|
|
|
|
| Accent::DDot
|
|
|
|
|
| Accent::OverBrace => format!(
|
|
|
|
|
"<mover accentover='true'><mrow>{}</mrow><mo>{}</mo></mover>",
|
|
|
|
|
self.inner.to_mathml(),
|
|
|
|
|
self.accent.to_mathml()
|
|
|
|
|
),
|
|
|
|
|
Accent::Underline | Accent::UnderBrace => format!(
|
|
|
|
|
"<munder accentunder='true'><mrow>{}</mrow><mo>{}</mo></mover>",
|
|
|
|
|
self.inner.to_mathml(),
|
|
|
|
|
self.accent.to_mathml()
|
|
|
|
|
),
|
|
|
|
|
_ => self.inner.to_mathml(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Group {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
Group::Vector(v) => v.to_mathml(),
|
|
|
|
|
Group::MSep => ",".to_string(),
|
|
|
|
|
Group::Parentheses(p) => p.to_mathml(),
|
|
|
|
|
Group::Brackets(b) => b.to_mathml(),
|
|
|
|
|
Group::Braces(b) => b.to_mathml(),
|
|
|
|
|
Group::Angles(a) => a.to_mathml(),
|
|
|
|
|
Group::XGroup(x) => x.to_mathml(),
|
|
|
|
|
Group::Abs(a) => a.to_mathml(),
|
|
|
|
|
Group::Floor(f) => f.to_mathml(),
|
|
|
|
|
Group::Ceil(c) => c.to_mathml(),
|
|
|
|
|
Group::Norm(n) => n.to_mathml(),
|
|
|
|
|
Group::Matrix(m) => m.to_mathml(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Parentheses {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>(</mo>{}<mo>)</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Brackets {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>[</mo>{}<mo>]</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Braces {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>{</mo>{}<mo>}</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Angles {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>⟨</mo>{}<mo>⟩</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for XGroup {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>(x</mo>{}<mo>x)</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Abs {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>|</mo>{}<mo>|</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Floor {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>⌊</mo>{}<mo>⌋</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Ceil {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>⌈</mo>{}<mo>⌉</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Norm {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>||</mo>{}<mo>||</mo></mrow>",
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Matrix {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>[</mo><mtable>{}</mtable><mo>]</mo></mrow>",
|
|
|
|
|
self.inner.iter().fold("".to_string(), |a, b| format!(
|
|
|
|
|
"{}<mtr>{}</mtr>",
|
|
|
|
|
a,
|
|
|
|
|
b.iter().fold("".to_string(), |a, b| format!(
|
|
|
|
|
"{}<mtd>{}</mtd>",
|
|
|
|
|
a,
|
|
|
|
|
b.to_mathml()
|
|
|
|
|
))
|
|
|
|
|
))
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Vector {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow><mo>(</mo><mtable>{}</mtable><mo>)</mo></mrow>",
|
|
|
|
|
self.inner.iter().fold("".to_string(), |a, b| format!(
|
|
|
|
|
"{}<mtr>{}</mtr>",
|
|
|
|
|
a,
|
|
|
|
|
b.iter().fold("".to_string(), |a, b| format!(
|
|
|
|
|
"{}<mtd>{}</mtd>",
|
|
|
|
|
a,
|
|
|
|
|
b.to_mathml()
|
|
|
|
|
))
|
|
|
|
|
))
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Special {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
Special::Sum(s) => s.to_mathml(),
|
|
|
|
|
Special::Prod(p) => p.to_mathml(),
|
|
|
|
|
Special::Frac(f) => f.to_mathml(),
|
|
|
|
|
Special::Pow(p) => p.to_mathml(),
|
|
|
|
|
Special::Sub(s) => s.to_mathml(),
|
|
|
|
|
Special::Sqrt(s) => s.to_mathml(),
|
|
|
|
|
Special::Root(r) => r.to_mathml(),
|
|
|
|
|
Special::Integral(i) => i.to_mathml(),
|
|
|
|
|
Special::OIntegral(i) => i.to_mathml(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Sum {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
if let Some(bottom) = &self.bottom {
|
|
|
|
|
if let Some(top) = &self.top {
|
|
|
|
|
format!(
|
|
|
|
|
"<munderover><mi>∑</mi>{}{}</munderover>",
|
|
|
|
|
bottom.to_mathml(),
|
|
|
|
|
top.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
format!("<munder><mi>∑</mi>{}</munder>", bottom.to_mathml())
|
|
|
|
|
}
|
|
|
|
|
} else if let Some(top) = &self.top {
|
|
|
|
|
format!("<mover><mi>∑<mi>{}</mover>", top.to_mathml())
|
|
|
|
|
} else {
|
|
|
|
|
format!("<mi>∑</mi>")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Prod {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
if let Some(bottom) = &self.bottom {
|
|
|
|
|
if let Some(top) = &self.top {
|
|
|
|
|
format!(
|
|
|
|
|
"<munderover><mi>∏</mi>{}{}</munderover>",
|
|
|
|
|
bottom.to_mathml(),
|
|
|
|
|
top.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
format!("<munder><mi>∏</mi>{}</munder>", bottom.to_mathml())
|
|
|
|
|
}
|
|
|
|
|
} else if let Some(top) = &self.top {
|
|
|
|
|
format!("<mover><mi>∏<mi>{}</mover>", top.to_mathml())
|
|
|
|
|
} else {
|
|
|
|
|
format!("<mi>∏</mi>")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Frac {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mfrac>{}{}</mfrac>",
|
|
|
|
|
self.top.to_mathml(),
|
|
|
|
|
self.bottom.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Sqrt {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!("<msqrt>{}</msqrt>", self.inner.to_mathml())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Root {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mroot>{}{}</mroot>",
|
|
|
|
|
self.base.to_mathml(),
|
|
|
|
|
self.inner.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Pow {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<msup>{}{}</msup>",
|
|
|
|
|
self.base.to_mathml(),
|
|
|
|
|
self.exp.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Sub {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<msub>{}{}</msub>",
|
|
|
|
|
self.base.to_mathml(),
|
|
|
|
|
self.lower.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Integral {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
if let Some(bottom) = &self.bottom {
|
|
|
|
|
if let Some(top) = &self.top {
|
|
|
|
|
format!(
|
|
|
|
|
"<munderover><mi>∫</mi>{}{}</munderover>",
|
|
|
|
|
bottom.to_mathml(),
|
|
|
|
|
top.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
format!("<munder><mi>∫</mi>{}</munder>", bottom.to_mathml())
|
|
|
|
|
}
|
|
|
|
|
} else if let Some(top) = &self.top {
|
|
|
|
|
format!("<mover><mi>∫<mi>{}</mover>", top.to_mathml())
|
|
|
|
|
} else {
|
|
|
|
|
format!("<mi>∫</mi>")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for OIntegral {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
if let Some(bottom) = &self.bottom {
|
|
|
|
|
if let Some(top) = &self.top {
|
|
|
|
|
format!(
|
|
|
|
|
"<munderover><mi>∮</mi>{}{}</munderover>",
|
|
|
|
|
bottom.to_mathml(),
|
|
|
|
|
top.to_mathml()
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
format!("<munder><mi>∮</mi>{}</munder>", bottom.to_mathml())
|
|
|
|
|
}
|
|
|
|
|
} else if let Some(top) = &self.top {
|
|
|
|
|
format!("<mover><mi>∮<mi>{}</mover>", top.to_mathml())
|
|
|
|
|
} else {
|
|
|
|
|
format!("<mi>∮</mi>")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for ExpressionAccent {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
ExpressionAccent::Generic(g) => g.to_mathml(),
|
|
|
|
|
ExpressionAccent::OverSet(o) => o.to_mathml(),
|
|
|
|
|
ExpressionAccent::UnderSet(u) => u.to_mathml(),
|
|
|
|
|
ExpressionAccent::Color(c) => c.to_mathml(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Expression {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"<mrow>{}</mrow>",
|
|
|
|
|
self.children
|
|
|
|
|
.iter()
|
|
|
|
|
.fold("".to_string(), |a, b| format!("{}{}", a, b.to_mathml()))
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ToMathML for Element {
|
|
|
|
|
fn to_mathml(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
Element::Special(s) => s.to_mathml(),
|
|
|
|
|
Element::Literal(l) => l.to_mathml(),
|
|
|
|
|
Element::Group(g) => g.to_mathml(),
|
|
|
|
|
Element::Accent(a) => a.to_mathml(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|