Add group tree parsing

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

@ -1,6 +1,6 @@
use crate::elements::special::Expression;
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Group {
Parentheses(Parentheses),
Brackets(Brackets),
@ -13,47 +13,47 @@ pub enum Group {
Norm(Norm),
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Parentheses {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Brackets {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Braces {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Angles {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct XGroup {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Abs {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Floor {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Ceil {
inner: Box<Expression>,
pub inner: Box<Expression>,
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
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};
#[derive(Clone, Debug)]
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Literal {
Integer,
Text(TextNode),
Symbol(SymbolNode),
Number(NumberNode),
Text(PlainText),
Symbol(Symbol),
Number(Number),
Greek(Greek),
FontCommand(FontCommand),
Relation(Relation),
@ -16,17 +16,17 @@ pub enum Literal {
Operation(Operation),
}
#[derive(Clone, Debug)]
pub struct TextNode {
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct PlainText {
pub(crate) text: String,
}
#[derive(Clone, Debug)]
pub struct SymbolNode {
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Symbol {
pub(crate) symbol: String,
}
#[derive(Clone, Debug)]
pub struct NumberNode {
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Number {
pub(crate) number: String,
}

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

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

@ -10,12 +10,18 @@ extern crate lazy_static;
pub mod elements;
pub mod parsing;
mod tokens;
mod utils;
#[cfg(test)]
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::tree_parser::TreeParser;
use crate::tokens::Function::Exp;
use crate::tokens::{Function, Grouping, Misc, Operation, Relation, Text, Token};
use crate::utils::Boxed;
use std::fs;
use test::Bencher;
@ -114,16 +120,41 @@ mod tests {
)
}
//#[test]
fn it_parses_into_a_tree() {
let expression = "sum_2^3 + 4^4";
#[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_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(
"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::{
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::tokens::{Misc, Operation, Text, Token};
use crate::tokens::{Grouping, Misc, Operation, Text, Token};
use crate::utils::Boxed;
pub struct TreeParser {
tokens: Vec<Token>,
index: usize,
group_return: bool,
}
impl TreeParser {
pub fn new(tokens: Vec<Token>) -> Self {
Self { tokens, index: 0 }
Self {
tokens,
index: 0,
group_return: false,
}
}
pub fn parse(&mut self) -> Expression {
@ -32,6 +41,8 @@ impl TreeParser {
}
})
.collect();
// add null end token to ensure that everything got parsed
self.tokens.push(Token::End)
}
fn step(&mut self) -> bool {
@ -63,8 +74,12 @@ impl TreeParser {
if let Some(element) = self.parse_element() {
expression.add_child(element);
}
if self.group_return {
break;
}
self.step();
}
self.group_return = false;
expression
}
@ -85,15 +100,22 @@ impl TreeParser {
}
Token::Operation(op) => Some(self.parse_operation(op)),
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,
}
}
fn parse_text(&self, token: Text) -> Option<Literal> {
match token {
Text::Symbol(s) => Some(Literal::Symbol(SymbolNode { symbol: s })),
Text::Number(n) => Some(Literal::Number(NumberNode { number: n })),
Text::Plain(p) => Some(Literal::Text(TextNode { text: p })),
Text::Symbol(s) => Some(Literal::Symbol(Symbol { symbol: s })),
Text::Number(n) => Some(Literal::Number(Number { number: n })),
Text::Plain(p) => Some(Literal::Text(PlainText { text: p })),
_ => None,
}
}
@ -126,6 +148,12 @@ impl TreeParser {
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 {
@ -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>> {
if let Some(Token::Misc(Misc::Sub)) = self.peek() {
self.step();

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

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

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