Add ToMathML for special elements and remaining enums

pull/2/head
trivernis 4 years ago
parent 1e7fc5ee21
commit b40485b391

@ -39,11 +39,13 @@ pub struct Frac {
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Pow {
pub(crate) base: Box<Element>,
pub(crate) exp: Box<Element>,
}
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Sub {
pub(crate) base: Box<Element>,
pub(crate) lower: Box<Element>,
}

@ -3,7 +3,9 @@ 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;
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,
@ -266,7 +268,7 @@ impl ToMathML for Operation {
let inner = match self {
Operation::Plus => "&plus;",
Operation::Minus => "&minus;",
Operation::CDot => "&#8729;",
Operation::CDot => "&sdot;",
Operation::Ast => "&lowast;",
Operation::Star => "&Star;",
Operation::Slash => "/",
@ -498,6 +500,159 @@ impl ToMathML for Vector {
}
}
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>&sum;</mi>{}{}</munderover>",
bottom.to_mathml(),
top.to_mathml()
)
} else {
format!("<munder><mi>&sum;</mi>{}</munder>", bottom.to_mathml())
}
} else if let Some(top) = &self.top {
format!("<mover><mi>&sum;<mi>{}</mover>", top.to_mathml())
} else {
format!("<mi>&sum;</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>&prod;</mi>{}{}</munderover>",
bottom.to_mathml(),
top.to_mathml()
)
} else {
format!("<munder><mi>&prod;</mi>{}</munder>", bottom.to_mathml())
}
} else if let Some(top) = &self.top {
format!("<mover><mi>&prod;<mi>{}</mover>", top.to_mathml())
} else {
format!("<mi>&prod;</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>&int;</mi>{}{}</munderover>",
bottom.to_mathml(),
top.to_mathml()
)
} else {
format!("<munder><mi>&int;</mi>{}</munder>", bottom.to_mathml())
}
} else if let Some(top) = &self.top {
format!("<mover><mi>&int;<mi>{}</mover>", top.to_mathml())
} else {
format!("<mi>&int;</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>&conint;</mi>{}{}</munderover>",
bottom.to_mathml(),
top.to_mathml()
)
} else {
format!("<munder><mi>&conint;</mi>{}</munder>", bottom.to_mathml())
}
} else if let Some(top) = &self.top {
format!("<mover><mi>&conint;<mi>{}</mover>", top.to_mathml())
} else {
format!("<mi>&conint;</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!(
@ -511,6 +666,11 @@ impl ToMathML for Expression {
impl ToMathML for Element {
fn to_mathml(&self) -> String {
unimplemented!()
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(),
}
}
}

@ -32,6 +32,7 @@ mod tests {
use crate::elements::literal::{Literal, Number};
use crate::elements::special::{Expression, Special, Sum};
use crate::elements::Element;
use crate::format::mathml::ToMathML;
use crate::parse;
use crate::parsing::tokenizer::Tokenizer;
use crate::parsing::tree_parser::TreeParser;
@ -347,15 +348,19 @@ mod tests {
)
}
#[allow(dead_code)]
//#[test]
fn it_parses_into_a_tree3() {
fn it_writes_mathml() {
let str_expression =
"sqrt 1 in NN implies 2^4 + sum_(k = 1)^3 - ((1),(2)) [[2, 3 + 3],[4, 5]]";
let expression = parse(str_expression.to_string());
fs::write(
"test-files/test.txt",
"test-files/test.html",
format!(
"{:#?}",
parse(
"color(red)(a) * b^4 - c(c-2) [[1, 3, 2 + 2],[3 - x, 4] ((2),(3))".to_string()
)
"<html><body><pre>{}</pre><math>{}</math><pre>{:#?}</pre></body></html>",
str_expression,
expression.to_mathml(),
expression,
),
)
.unwrap();

@ -73,7 +73,16 @@ impl TreeParser {
while !self.end_reached() {
if let Some(element) = self.parse_element() {
expression.add_child(element);
// parse elements that are based on the previous one
if let Some(pow) = self.parse_pow_element(&element) {
expression.add_child(Element::Special(Special::Pow(pow)))
} else if let Some(frac) = self.parse_frac_element(&element) {
expression.add_child(Element::Special(Special::Frac(frac)))
} else if let Some(sub) = self.parse_sub_element(&element) {
expression.add_child(Element::Special(Special::Sub(sub)))
} else {
expression.add_child(element);
}
}
if self.group_return {
break;
@ -214,18 +223,6 @@ impl TreeParser {
fn parse_misc(&mut self, token: Misc) -> Element {
match token {
Misc::Pow => {
self.step();
Element::Special(Special::Pow(Pow {
exp: self.parse_element().unwrap().boxed(),
}))
}
Misc::Sub => {
self.step();
Element::Special(Special::Sub(Sub {
lower: self.parse_element().unwrap().boxed(),
}))
}
Misc::LatexFrac => {
self.step();
Element::Special(Special::Frac(Frac {
@ -427,6 +424,48 @@ impl TreeParser {
}
}
// tries to parse a pow element
fn parse_pow_element(&mut self, previous: &Element) -> Option<Pow> {
if let Some(Token::Misc(Misc::Pow)) = self.peek() {
self.step();
self.step();
Some(Pow {
base: previous.clone().boxed(),
exp: self.parse_element().unwrap().boxed(),
})
} else {
None
}
}
// tries to parse a sub element
fn parse_sub_element(&mut self, previous: &Element) -> Option<Sub> {
if let Some(Token::Misc(Misc::Sub)) = self.peek() {
self.step();
self.step();
Some(Sub {
base: previous.clone().boxed(),
lower: self.parse_element().unwrap().boxed(),
})
} else {
None
}
}
// tries to parse an ascii frac
fn parse_frac_element(&mut self, previous: &Element) -> Option<Frac> {
if let Some(Token::Misc(Misc::AsciiFrac)) = self.peek() {
self.step();
self.step();
Some(Frac {
top: previous.clone().boxed(),
bottom: self.parse_element().unwrap().boxed(),
})
} else {
None
}
}
/// Remaps an expresion vector into a matrix of expressions by splitting on each MSep token
fn transform_vec_to_matrix(&self, expressions: Vec<Expression>) -> Vec<Vec<Expression>> {
expressions

Loading…
Cancel
Save