Add group tree parsing

pull/1/head
trivernis 4 years ago
parent 05380323c8
commit d01700dfb6

@ -1,6 +1,6 @@
use crate::elements::special::Expression; use crate::elements::special::Expression;
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Group { pub enum Group {
Parentheses(Parentheses), Parentheses(Parentheses),
Brackets(Brackets), Brackets(Brackets),
@ -13,47 +13,47 @@ pub enum Group {
Norm(Norm), Norm(Norm),
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Parentheses { pub struct Parentheses {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Brackets { pub struct Brackets {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Braces { pub struct Braces {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Angles { pub struct Angles {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct XGroup { pub struct XGroup {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Abs { pub struct Abs {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Floor { pub struct Floor {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Ceil { pub struct Ceil {
inner: Box<Expression>, pub inner: Box<Expression>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Norm { pub struct Norm {
inner: Box<Expression>, pub inner: Box<Expression>,
} }

@ -1,11 +1,11 @@
use crate::tokens::{Arrow, FontCommand, Function, Greek, Logical, Misc, Operation, Relation}; use crate::tokens::{Arrow, FontCommand, Function, Greek, Logical, Misc, Operation, Relation};
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Literal { pub enum Literal {
Integer, Integer,
Text(TextNode), Text(PlainText),
Symbol(SymbolNode), Symbol(Symbol),
Number(NumberNode), Number(Number),
Greek(Greek), Greek(Greek),
FontCommand(FontCommand), FontCommand(FontCommand),
Relation(Relation), Relation(Relation),
@ -16,17 +16,17 @@ pub enum Literal {
Operation(Operation), Operation(Operation),
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct TextNode { pub struct PlainText {
pub(crate) text: String, pub(crate) text: String,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct SymbolNode { pub struct Symbol {
pub(crate) symbol: String, pub(crate) symbol: String,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct NumberNode { pub struct Number {
pub(crate) number: String, pub(crate) number: String,
} }

@ -1,20 +1,17 @@
use crate::elements::group::Group; use crate::elements::group::Group;
use crate::elements::literal::Literal; use crate::elements::literal::Literal;
use crate::elements::special::Special; use crate::elements::special::Special;
use crate::utils::Boxed;
pub mod group; pub mod group;
pub mod literal; pub mod literal;
pub mod special; pub mod special;
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Element { pub enum Element {
Literal(Literal), Literal(Literal),
Special(Special), Special(Special),
Group(Group), Group(Group),
} }
impl Element { impl Boxed for Element {}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
}

@ -1,63 +1,70 @@
use crate::elements::Element; use crate::elements::Element;
use crate::utils::Boxed;
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Expression { pub struct Expression {
children: Vec<Element>, children: Vec<Element>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Special { pub enum Special {
Sum(Sum), Sum(Sum),
Prod(Prod), Prod(Prod),
Frac(Frac), Frac(Frac),
Pow(Pow), Pow(Pow),
Sub(Sub),
Sqrt(Sqrt), Sqrt(Sqrt),
Root(Root), Root(Root),
Integral(Integral), Integral(Integral),
OIntegral(OIntegral), OIntegral(OIntegral),
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Sum { pub struct Sum {
pub top: Option<Box<Element>>, pub top: Option<Box<Element>>,
pub bottom: Option<Box<Element>>, pub bottom: Option<Box<Element>>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Prod { pub struct Prod {
pub top: Option<Box<Element>>, pub top: Option<Box<Element>>,
pub bottom: Option<Box<Element>>, pub bottom: Option<Box<Element>>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Frac { pub struct Frac {
pub(crate) top: Box<Element>, pub(crate) top: Box<Element>,
pub(crate) bottom: Box<Element>, pub(crate) bottom: Box<Element>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Pow { pub struct Pow {
pub(crate) exp: Box<Element>, pub(crate) exp: Box<Element>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Sub {
pub(crate) lower: Box<Element>,
}
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Sqrt { pub struct Sqrt {
pub(crate) inner: Box<Element>, pub(crate) inner: Box<Element>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Root { pub struct Root {
pub(crate) base: Box<Element>, pub(crate) base: Box<Element>,
pub(crate) inner: Box<Element>, pub(crate) inner: Box<Element>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Integral { pub struct Integral {
pub(crate) top: Option<Box<Element>>, pub(crate) top: Option<Box<Element>>,
pub(crate) bottom: Option<Box<Element>>, pub(crate) bottom: Option<Box<Element>>,
} }
#[derive(Clone, Debug)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct OIntegral { pub struct OIntegral {
pub(crate) top: Option<Box<Element>>, pub(crate) top: Option<Box<Element>>,
pub(crate) bottom: Option<Box<Element>>, pub(crate) bottom: Option<Box<Element>>,
@ -75,6 +82,8 @@ impl Expression {
} }
} }
impl Boxed for Expression {}
impl Sum { impl Sum {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {

@ -10,12 +10,18 @@ extern crate lazy_static;
pub mod elements; pub mod elements;
pub mod parsing; pub mod parsing;
mod tokens; mod tokens;
mod utils;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::elements::literal::{Literal, Number};
use crate::elements::special::{Expression, Special, Sum};
use crate::elements::Element;
use crate::parsing::tokenizer::Tokenizer; use crate::parsing::tokenizer::Tokenizer;
use crate::parsing::tree_parser::TreeParser; use crate::parsing::tree_parser::TreeParser;
use crate::tokens::Function::Exp;
use crate::tokens::{Function, Grouping, Misc, Operation, Relation, Text, Token}; use crate::tokens::{Function, Grouping, Misc, Operation, Relation, Text, Token};
use crate::utils::Boxed;
use std::fs; use std::fs;
use test::Bencher; use test::Bencher;
@ -114,16 +120,41 @@ mod tests {
) )
} }
//#[test] #[test]
fn it_parses_into_a_tree() { fn it_parses_into_a_tree1() {
let expression = "sum_2^3 + 4^4"; let expression = "sum_2^3";
let mut tokenizer = Tokenizer::new(expression.to_string()); let mut tokenizer = Tokenizer::new(expression.to_string());
let tokens = tokenizer.parse(); let tokens = tokenizer.parse();
let mut tree_parser = TreeParser::new(tokens.clone()); let mut tree_parser = TreeParser::new(tokens.clone());
let expression = tree_parser.parse(); 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_into_a_tree2() {
let str_expression = "sum_2^3 + abs(4^4) - 1^(2*2)_2";
let mut tokenizer = Tokenizer::new(str_expression.to_string());
let tokens = tokenizer.parse();
let mut tree_parser = TreeParser::new(tokens.clone());
let expression = tree_parser.parse();
fs::write( fs::write(
"test-files/test.txt", "test-files/test.txt",
format!("{:?}\n\n{:?}", tokens, expression), format!("{}\n\n{:?}\n\n{:#?}", str_expression, tokens, expression),
); );
} }

@ -1,18 +1,27 @@
use crate::elements::literal::{Literal, NumberNode, SymbolNode, TextNode}; use crate::elements::group::{
Abs, Angles, Braces, Brackets, Ceil, Floor, Group, Norm, Parentheses, XGroup,
};
use crate::elements::literal::{Literal, Number, PlainText, Symbol};
use crate::elements::special::{ use crate::elements::special::{
Expression, Frac, Integral, OIntegral, Pow, Prod, Root, Special, Sqrt, Sum, Expression, Frac, Integral, OIntegral, Pow, Prod, Root, Special, Sqrt, Sub, Sum,
}; };
use crate::elements::Element; use crate::elements::Element;
use crate::tokens::{Misc, Operation, Text, Token}; use crate::tokens::{Grouping, Misc, Operation, Text, Token};
use crate::utils::Boxed;
pub struct TreeParser { pub struct TreeParser {
tokens: Vec<Token>, tokens: Vec<Token>,
index: usize, index: usize,
group_return: bool,
} }
impl TreeParser { impl TreeParser {
pub fn new(tokens: Vec<Token>) -> Self { pub fn new(tokens: Vec<Token>) -> Self {
Self { tokens, index: 0 } Self {
tokens,
index: 0,
group_return: false,
}
} }
pub fn parse(&mut self) -> Expression { pub fn parse(&mut self) -> Expression {
@ -32,6 +41,8 @@ impl TreeParser {
} }
}) })
.collect(); .collect();
// add null end token to ensure that everything got parsed
self.tokens.push(Token::End)
} }
fn step(&mut self) -> bool { fn step(&mut self) -> bool {
@ -63,8 +74,12 @@ impl TreeParser {
if let Some(element) = self.parse_element() { if let Some(element) = self.parse_element() {
expression.add_child(element); expression.add_child(element);
} }
if self.group_return {
break;
}
self.step(); self.step();
} }
self.group_return = false;
expression expression
} }
@ -85,15 +100,22 @@ impl TreeParser {
} }
Token::Operation(op) => Some(self.parse_operation(op)), Token::Operation(op) => Some(self.parse_operation(op)),
Token::Misc(m) => Some(self.parse_misc(m)), Token::Misc(m) => Some(self.parse_misc(m)),
Token::Grouping(g) => {
if let Some(group) = self.parse_group(g) {
Some(Element::Group(group))
} else {
None
}
}
_ => None, _ => None,
} }
} }
fn parse_text(&self, token: Text) -> Option<Literal> { fn parse_text(&self, token: Text) -> Option<Literal> {
match token { match token {
Text::Symbol(s) => Some(Literal::Symbol(SymbolNode { symbol: s })), Text::Symbol(s) => Some(Literal::Symbol(Symbol { symbol: s })),
Text::Number(n) => Some(Literal::Number(NumberNode { number: n })), Text::Number(n) => Some(Literal::Number(Number { number: n })),
Text::Plain(p) => Some(Literal::Text(TextNode { text: p })), Text::Plain(p) => Some(Literal::Text(PlainText { text: p })),
_ => None, _ => None,
} }
} }
@ -126,6 +148,12 @@ impl TreeParser {
exp: self.parse_element().unwrap().boxed(), 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 {
@ -158,6 +186,68 @@ impl TreeParser {
} }
} }
fn parse_group(&mut self, token: Grouping) -> Option<Group> {
match token {
Grouping::RParen => {
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Parentheses(Parentheses { inner }))
}
Grouping::RBrace => {
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Braces(Braces { inner }))
}
Grouping::RBracket => {
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Brackets(Brackets { inner }))
}
Grouping::RAngle => {
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Angles(Angles { inner }))
}
Grouping::RXPar => {
self.step();
let inner = self.parse_expression().boxed();
Some(Group::XGroup(XGroup { inner }))
}
Grouping::Abs => {
self.step();
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Abs(Abs { inner }))
}
Grouping::Floor => {
self.step();
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Floor(Floor { inner }))
}
Grouping::Ceil => {
self.step();
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Ceil(Ceil { inner }))
}
Grouping::Norm => {
self.step();
self.step();
let inner = self.parse_expression().boxed();
Some(Group::Norm(Norm { inner }))
}
_ => {
self.group_return = true;
None
}
}
}
fn parse_sub(&mut self) -> Option<Box<Element>> { fn parse_sub(&mut self) -> Option<Box<Element>> {
if let Some(Token::Misc(Misc::Sub)) = self.peek() { if let Some(Token::Misc(Misc::Sub)) = self.peek() {
self.step(); self.step();

@ -163,10 +163,10 @@ pub fn get_grouping_mappings() -> Vec<HashMap<TokenPattern, Grouping>> {
hashmap! { hashmap! {
G_RPAREN => Grouping::RParen, G_RPAREN => Grouping::RParen,
G_LPAREN => Grouping::LParen, G_LPAREN => Grouping::LParen,
G_RBRAC => Grouping::RBrace, G_RBRAC => Grouping::RBracket,
G_LBRAC => Grouping::LBrace, G_LBRAC => Grouping::LBracket,
G_RCURL => Grouping::RCurl, G_RCURL => Grouping::RBrace,
G_LCURL => Grouping::LCurl, G_LCURL => Grouping::LBrace,
G_ABS => Grouping::Abs, G_ABS => Grouping::Abs,
G_FLOOR => Grouping::Floor, G_FLOOR => Grouping::Floor,
G_CEIL => Grouping::Ceil, G_CEIL => Grouping::Ceil,

@ -14,6 +14,7 @@ pub enum Token {
Font(FontCommand), Font(FontCommand),
Function(Function), Function(Function),
Text(Text), Text(Text),
End,
} }
#[derive(Debug, Clone, PartialOrd, PartialEq)] #[derive(Debug, Clone, PartialOrd, PartialEq)]
@ -139,10 +140,10 @@ pub enum Logical {
pub enum Grouping { pub enum Grouping {
RParen, RParen,
LParen, LParen,
RBracket,
LBracket,
RBrace, RBrace,
LBrace, LBrace,
RCurl,
LCurl,
LAngle, LAngle,
RAngle, RAngle,
LXPar, LXPar,

@ -0,0 +1,8 @@
pub trait Boxed
where
Self: std::marker::Sized,
{
fn boxed(self) -> Box<Self> {
Box::new(self)
}
}
Loading…
Cancel
Save