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)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Pow { pub struct Pow {
pub(crate) base: Box<Element>,
pub(crate) exp: Box<Element>, pub(crate) exp: Box<Element>,
} }
#[derive(Debug, Clone, PartialOrd, PartialEq)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Sub { pub struct Sub {
pub(crate) base: Box<Element>,
pub(crate) lower: 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, Abs, Angles, Braces, Brackets, Ceil, Floor, Group, Matrix, Norm, Parentheses, Vector, XGroup,
}; };
use crate::elements::literal::{Literal, Number, PlainText, Symbol}; 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::elements::Element;
use crate::tokens::{ use crate::tokens::{
Accent, Arrow, FontCommand, Function, Greek, Logical, Misc, Operation, Relation, Accent, Arrow, FontCommand, Function, Greek, Logical, Misc, Operation, Relation,
@ -266,7 +268,7 @@ impl ToMathML for Operation {
let inner = match self { let inner = match self {
Operation::Plus => "&plus;", Operation::Plus => "&plus;",
Operation::Minus => "&minus;", Operation::Minus => "&minus;",
Operation::CDot => "&#8729;", Operation::CDot => "&sdot;",
Operation::Ast => "&lowast;", Operation::Ast => "&lowast;",
Operation::Star => "&Star;", Operation::Star => "&Star;",
Operation::Slash => "/", 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 { impl ToMathML for Expression {
fn to_mathml(&self) -> String { fn to_mathml(&self) -> String {
format!( format!(
@ -511,6 +666,11 @@ impl ToMathML for Expression {
impl ToMathML for Element { impl ToMathML for Element {
fn to_mathml(&self) -> String { 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::literal::{Literal, Number};
use crate::elements::special::{Expression, Special, Sum}; use crate::elements::special::{Expression, Special, Sum};
use crate::elements::Element; use crate::elements::Element;
use crate::format::mathml::ToMathML;
use crate::parse; use crate::parse;
use crate::parsing::tokenizer::Tokenizer; use crate::parsing::tokenizer::Tokenizer;
use crate::parsing::tree_parser::TreeParser; use crate::parsing::tree_parser::TreeParser;
@ -347,15 +348,19 @@ mod tests {
) )
} }
#[allow(dead_code)]
//#[test] //#[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( fs::write(
"test-files/test.txt", "test-files/test.html",
format!( format!(
"{:#?}", "<html><body><pre>{}</pre><math>{}</math><pre>{:#?}</pre></body></html>",
parse( str_expression,
"color(red)(a) * b^4 - c(c-2) [[1, 3, 2 + 2],[3 - x, 4] ((2),(3))".to_string() expression.to_mathml(),
) expression,
), ),
) )
.unwrap(); .unwrap();

@ -73,7 +73,16 @@ impl TreeParser {
while !self.end_reached() { while !self.end_reached() {
if let Some(element) = self.parse_element() { 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 { if self.group_return {
break; break;
@ -214,18 +223,6 @@ impl TreeParser {
fn parse_misc(&mut self, token: Misc) -> Element { fn parse_misc(&mut self, token: Misc) -> Element {
match token { 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 => { Misc::LatexFrac => {
self.step(); self.step();
Element::Special(Special::Frac(Frac { 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 /// 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>> { fn transform_vec_to_matrix(&self, expressions: Vec<Expression>) -> Vec<Vec<Expression>> {
expressions expressions

Loading…
Cancel
Save