commit
43577debda
@ -0,0 +1,11 @@
|
||||
use crate::format::mathml::ToMathML;
|
||||
use crate::parse;
|
||||
|
||||
#[test]
|
||||
fn it_renders_roots() {
|
||||
let expr = parse("root 3 16".to_string());
|
||||
assert_eq!(
|
||||
expr.to_mathml(),
|
||||
"<mrow><mroot><mn>16</mn><mn>3</mn></mroot></mrow>"
|
||||
)
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
mod mathml;
|
||||
mod parsing;
|
||||
mod tokenization;
|
@ -0,0 +1,250 @@
|
||||
use crate::elements::group::{Brackets, Group, Matrix, Parentheses, Vector};
|
||||
use crate::elements::literal::{Literal, Number};
|
||||
use crate::elements::special::{Expression, Root, Special, Sum};
|
||||
use crate::elements::Element;
|
||||
use crate::parse;
|
||||
use crate::parsing::tokenizer::Tokenizer;
|
||||
use crate::parsing::tree_parser::TreeParser;
|
||||
use crate::tokens::{Function, Operation};
|
||||
use crate::utils::Boxed;
|
||||
|
||||
#[test]
|
||||
fn it_parses_into_a_tree1() {
|
||||
let expression = "sum_2^3";
|
||||
let mut tokenizer = Tokenizer::new(expression.to_string());
|
||||
let tokens = tokenizer.parse();
|
||||
let mut tree_parser = TreeParser::new(tokens.clone());
|
||||
let expression = tree_parser.parse();
|
||||
let mut test_expression = Expression::new();
|
||||
test_expression.add_child(Element::Special(Special::Sum(Sum {
|
||||
bottom: Some(
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "2".to_string(),
|
||||
}))
|
||||
.boxed(),
|
||||
),
|
||||
top: Some(
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "3".to_string(),
|
||||
}))
|
||||
.boxed(),
|
||||
),
|
||||
})));
|
||||
assert_eq!(expression, test_expression)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_parses_matrices() {
|
||||
assert_eq!(
|
||||
parse("[[1, 2],[3,4]]".to_string()),
|
||||
Expression {
|
||||
children: vec![Element::Group(Group::Matrix(Matrix {
|
||||
inner: vec![
|
||||
vec![
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "1".to_string()
|
||||
})),]
|
||||
},
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "2".to_string()
|
||||
})),]
|
||||
}
|
||||
],
|
||||
vec![
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "3".to_string()
|
||||
})),]
|
||||
},
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "4".to_string()
|
||||
})),]
|
||||
}
|
||||
]
|
||||
]
|
||||
}))]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_rejects_invalid_matrices() {
|
||||
assert_eq!(
|
||||
parse("[[1, 3, 4],[3,4]]".to_string()),
|
||||
Expression {
|
||||
children: vec![Element::Group(Group::Brackets(Brackets {
|
||||
inner: Expression {
|
||||
children: vec![
|
||||
Element::Group(Group::Brackets(Brackets {
|
||||
inner: Expression {
|
||||
children: vec![
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "1".to_string()
|
||||
})),
|
||||
Element::Group(Group::MSep),
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "3".to_string()
|
||||
})),
|
||||
Element::Group(Group::MSep),
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "4".to_string()
|
||||
}))
|
||||
]
|
||||
}
|
||||
.boxed()
|
||||
})),
|
||||
Element::Group(Group::MSep),
|
||||
Element::Group(Group::Brackets(Brackets {
|
||||
inner: Expression {
|
||||
children: vec![
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "3".to_string()
|
||||
})),
|
||||
Element::Group(Group::MSep),
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "4".to_string()
|
||||
}))
|
||||
]
|
||||
}
|
||||
.boxed()
|
||||
}))
|
||||
]
|
||||
}
|
||||
.boxed()
|
||||
}))]
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
parse("[[1]]".to_string()),
|
||||
Expression {
|
||||
children: vec![Element::Group(Group::Brackets(Brackets {
|
||||
inner: Expression {
|
||||
children: vec![Element::Group(Group::Brackets(Brackets {
|
||||
inner: Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "1".to_string()
|
||||
})),]
|
||||
}
|
||||
.boxed()
|
||||
})),]
|
||||
}
|
||||
.boxed()
|
||||
}))]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_parses_vectors() {
|
||||
assert_eq!(
|
||||
parse("((1), (2))(1,2) - f".to_string()),
|
||||
Expression {
|
||||
children: vec![
|
||||
Element::Group(Group::Vector(Vector {
|
||||
inner: vec![
|
||||
vec![Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "1".to_string()
|
||||
}))]
|
||||
}],
|
||||
vec![Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "2".to_string()
|
||||
}))]
|
||||
}]
|
||||
]
|
||||
})),
|
||||
Element::Group(Group::Parentheses(Parentheses {
|
||||
inner: Expression {
|
||||
children: vec![
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "1".to_string()
|
||||
})),
|
||||
Element::Group(Group::MSep),
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "2".to_string()
|
||||
}))
|
||||
]
|
||||
}
|
||||
.boxed()
|
||||
})),
|
||||
Element::Literal(Literal::Operation(Operation::Minus)),
|
||||
Element::Literal(Literal::Function(Function::F))
|
||||
]
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
parse("((1, 3), (2, 5))".to_string()),
|
||||
Expression {
|
||||
children: vec![Element::Group(Group::Vector(Vector {
|
||||
inner: vec![
|
||||
vec![
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "1".to_string()
|
||||
}))]
|
||||
},
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "3".to_string()
|
||||
}))]
|
||||
}
|
||||
],
|
||||
vec![
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "2".to_string()
|
||||
}))]
|
||||
},
|
||||
Expression {
|
||||
children: vec![Element::Literal(Literal::Number(Number {
|
||||
number: "5".to_string()
|
||||
}))]
|
||||
}
|
||||
]
|
||||
]
|
||||
}))]
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_parses_roots() {
|
||||
let expr = parse("root 3 16".to_string());
|
||||
assert_eq!(
|
||||
expr,
|
||||
Expression {
|
||||
children: vec![Element::Special(Special::Root(Root {
|
||||
base: Element::Literal(Literal::Number(Number {
|
||||
number: "3".to_string()
|
||||
}))
|
||||
.boxed(),
|
||||
inner: Element::Literal(Literal::Number(Number {
|
||||
number: "16".to_string()
|
||||
}))
|
||||
.boxed(),
|
||||
}))]
|
||||
}
|
||||
);
|
||||
// test no fail
|
||||
parse("root 3".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_parses_functions() {
|
||||
let expr = parse("sin 10".to_string());
|
||||
assert_eq!(
|
||||
expr,
|
||||
Expression {
|
||||
children: vec![
|
||||
Element::Literal(Literal::Function(Function::Sin)),
|
||||
Element::Literal(Literal::Number(Number {
|
||||
number: "10".to_string()
|
||||
}))
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
use crate::parsing::tokenizer::Tokenizer;
|
||||
use crate::tokens::{Function, Grouping, Misc, Operation, Relation, Text, Token};
|
||||
|
||||
#[test]
|
||||
fn it_tokenizes_expressions1() {
|
||||
let expression = "sum_(i=1)^n*sin(x)";
|
||||
let mut tokenizer = Tokenizer::new(expression.to_string());
|
||||
let tokens = tokenizer.parse();
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Token::Operation(Operation::Sum),
|
||||
Token::Misc(Misc::Sub),
|
||||
Token::Grouping(Grouping::RParen),
|
||||
Token::Text(Text::Symbol("i".to_string())),
|
||||
Token::Relation(Relation::Eq),
|
||||
Token::Text(Text::Number("1".to_string())),
|
||||
Token::Grouping(Grouping::LParen),
|
||||
Token::Misc(Misc::Pow),
|
||||
Token::Text(Text::Symbol("n".to_string())),
|
||||
Token::Operation(Operation::CDot),
|
||||
Token::Function(Function::Sin),
|
||||
Token::Grouping(Grouping::RParen),
|
||||
Token::Text(Text::Symbol("x".to_string())),
|
||||
Token::Grouping(Grouping::LParen),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_tokenizes_expressions2() {
|
||||
let expression = "G_(11) = 5.16e6 € * (215)/(170) = 6.53e6";
|
||||
let mut tokenizer = Tokenizer::new(expression.to_string());
|
||||
let tokens = tokenizer.parse();
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Token::Text(Text::Symbol("G".to_string())),
|
||||
Token::Misc(Misc::Sub),
|
||||
Token::Grouping(Grouping::RParen),
|
||||
Token::Text(Text::Number("11".to_string())),
|
||||
Token::Grouping(Grouping::LParen),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Relation(Relation::Eq),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::Number("5.16e6".to_string())),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::Symbol("€".to_string())),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Operation(Operation::CDot),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Grouping(Grouping::RParen),
|
||||
Token::Text(Text::Number("215".to_string())),
|
||||
Token::Grouping(Grouping::LParen),
|
||||
Token::Misc(Misc::AsciiFrac),
|
||||
Token::Grouping(Grouping::RParen),
|
||||
Token::Text(Text::Number("170".to_string())),
|
||||
Token::Grouping(Grouping::LParen),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Relation(Relation::Eq),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::Number("6.53e6".to_string()))
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_tokenizes_expressions3() {
|
||||
let expression = "[[1, 2],[3, 4]] // \\\n";
|
||||
let mut tokenizer = Tokenizer::new(expression.to_string());
|
||||
let tokens = tokenizer.parse();
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Token::Grouping(Grouping::RBracket),
|
||||
Token::Grouping(Grouping::RBracket),
|
||||
Token::Text(Text::Number("1".to_string())),
|
||||
Token::Grouping(Grouping::MSep),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::Number("2".to_string())),
|
||||
Token::Grouping(Grouping::LBracket),
|
||||
Token::Grouping(Grouping::MSep),
|
||||
Token::Grouping(Grouping::RBracket),
|
||||
Token::Text(Text::Number("3".to_string())),
|
||||
Token::Grouping(Grouping::MSep),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::Number("4".to_string())),
|
||||
Token::Grouping(Grouping::LBracket),
|
||||
Token::Grouping(Grouping::LBracket),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Operation(Operation::Slash),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::NewLine),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_tokenizes_text1() {
|
||||
let expression = "\"just plain text\"";
|
||||
let mut tokenizer = Tokenizer::new(expression.to_string());
|
||||
let tokens = tokenizer.parse();
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![Token::Text(Text::Plain("just plain text".to_string()))]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_tokenizes_text2() {
|
||||
let expression = "\"plain text\" * \"plain text 2\" + a";
|
||||
let mut tokenizer = Tokenizer::new(expression.to_string());
|
||||
let tokens = tokenizer.parse();
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Token::Text(Text::Plain("plain text".to_string())),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Operation(Operation::CDot),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::Plain("plain text 2".to_string())),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Operation(Operation::Plus),
|
||||
Token::Text(Text::Whitespace),
|
||||
Token::Text(Text::Symbol("a".to_string()))
|
||||
]
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue