Add flat parsing functions to tree_parser

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

@ -1,57 +1,7 @@
use crate::tokens::{Arrow, FontCommand, Function, Greek, Logical, Relation};
use crate::tokens::{Arrow, FontCommand, Function, Greek, Logical, Misc, Operation, Relation};
#[derive(Clone, Debug)]
pub enum Literal {
Plus,
Minus,
CDot,
Ast,
Star,
Slash,
Backslash,
Times,
Div,
LTimes,
RTimes,
Bowtie,
Circ,
OPlus,
OTimes,
ODot,
Wedge,
BidWedge,
Vee,
Cap,
BigCap,
Cup,
BigCup,
Del,
Grad,
PlusMinus,
EmptySet,
Infty,
Aleph,
Therefore,
Because,
LDots,
CDots,
VDots,
DDots,
EPipes,
Quad,
Angle,
Frown,
Triangle,
Diamond,
Square,
LFloor,
RFloor,
LCeiling,
RCeiling,
Complex,
Natural,
Rational,
Real,
Integer,
Text(TextNode),
Symbol(SymbolNode),
@ -62,19 +12,21 @@ pub enum Literal {
Function(Function),
Logical(Logical),
Arrow(Arrow),
Misc(Misc),
Operation(Operation),
}
#[derive(Clone, Debug)]
pub struct TextNode {
text: String,
pub(crate) text: String,
}
#[derive(Clone, Debug)]
pub struct SymbolNode {
symbol: String,
pub(crate) symbol: String,
}
#[derive(Clone, Debug)]
pub struct NumberNode {
number: String,
pub(crate) number: String,
}

@ -12,3 +12,9 @@ pub enum Element {
Special(Special),
Group(Group),
}
impl Element {
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
}

@ -10,7 +10,7 @@ pub enum Special {
Sum(Sum),
Prod(Prod),
Frac(Frac),
Exp(Exp),
Pow(Pow),
Sqrt(Sqrt),
Root(Root),
Integral(Integral),
@ -19,47 +19,76 @@ pub enum Special {
#[derive(Clone, Debug)]
pub struct Sum {
top: Option<Expression>,
bottom: Option<Expression>,
pub top: Option<Box<Element>>,
pub bottom: Option<Box<Element>>,
}
#[derive(Clone, Debug)]
pub struct Prod {
top: Box<Expression>,
bottom: Box<Expression>,
pub top: Option<Box<Element>>,
pub bottom: Option<Box<Element>>,
}
#[derive(Clone, Debug)]
pub struct Frac {
top: Box<Expression>,
bottom: Box<Expression>,
pub(crate) top: Box<Element>,
pub(crate) bottom: Box<Element>,
}
#[derive(Clone, Debug)]
pub struct Exp {
base: Box<Element>,
exp: Box<Expression>,
pub struct Pow {
pub(crate) exp: Box<Element>,
}
#[derive(Clone, Debug)]
pub struct Sqrt {
inner: Box<Expression>,
pub(crate) inner: Box<Element>,
}
#[derive(Clone, Debug)]
pub struct Root {
base: Box<Expression>,
inner: Box<Expression>,
pub(crate) base: Box<Element>,
pub(crate) inner: Box<Element>,
}
#[derive(Clone, Debug)]
pub struct Integral {
top: Box<Expression>,
bottom: Box<Expression>,
pub(crate) top: Option<Box<Element>>,
pub(crate) bottom: Option<Box<Element>>,
}
#[derive(Clone, Debug)]
pub struct OIntegral {
top: Box<Expression>,
bottom: Box<Expression>,
pub(crate) top: Option<Box<Element>>,
pub(crate) bottom: Option<Box<Element>>,
}
impl Expression {
pub fn new() -> Self {
Self {
children: Vec::new(),
}
}
pub fn add_child(&mut self, child: Element) {
self.children.push(child)
}
}
impl Sum {
pub fn new() -> Self {
Self {
bottom: None,
top: None,
}
}
}
impl Prod {
pub fn new() -> Self {
Self {
bottom: None,
top: None,
}
}
}

@ -14,7 +14,9 @@ mod tokens;
#[cfg(test)]
mod tests {
use crate::parsing::tokenizer::Tokenizer;
use crate::parsing::tree_parser::TreeParser;
use crate::tokens::{Function, Grouping, Misc, Operation, Relation, Text, Token};
use std::fs;
use test::Bencher;
#[test]
@ -112,6 +114,19 @@ mod tests {
)
}
//#[test]
fn it_parses_into_a_tree() {
let expression = "sum_2^3 + 4^4";
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();
fs::write(
"test-files/test.txt",
format!("{:?}\n\n{:?}", tokens, expression),
);
}
#[bench]
fn bench_tokenizer(b: &mut Bencher) {
let expression = "sum_(iiiiiiiii=1)^n i^3=((n(n+1))/2)^2";

@ -1,5 +1,188 @@
use crate::tokens::Token;
use crate::elements::literal::{Literal, NumberNode, SymbolNode, TextNode};
use crate::elements::special::{
Expression, Frac, Integral, OIntegral, Pow, Prod, Root, Special, Sqrt, Sum,
};
use crate::elements::Element;
use crate::tokens::{Misc, Operation, Text, Token};
pub struct TreeParser {
tokens: Vec<Token>,
index: usize,
}
impl TreeParser {
pub fn new(tokens: Vec<Token>) -> Self {
Self { tokens, index: 0 }
}
pub fn parse(&mut self) -> Expression {
self.remove_whitespace();
self.parse_expression()
}
fn remove_whitespace(&mut self) {
self.tokens = self
.tokens
.iter()
.filter_map(|t| {
if let Token::Text(Text::Whitespace) = t {
None
} else {
Some(t.clone())
}
})
.collect();
}
fn step(&mut self) -> bool {
if self.index < (self.tokens.len() - 1) {
self.index += 1;
true
} else {
false
}
}
fn end_reached(&mut self) -> bool {
self.index >= (self.tokens.len() - 1)
}
fn peek(&mut self) -> Option<&Token> {
self.tokens.get(self.index + 1)
}
fn current_token(&self) -> &Token {
self.tokens.get(self.index).unwrap()
}
fn parse_expression(&mut self) -> Expression {
let mut expression = Expression::new();
while !self.end_reached() {
if let Some(element) = self.parse_element() {
expression.add_child(element);
}
self.step();
}
expression
}
fn parse_element(&mut self) -> Option<Element> {
let token = self.current_token().clone();
match token {
Token::Arrow(a) => Some(Element::Literal(Literal::Arrow(a.clone()))),
Token::Logical(l) => Some(Element::Literal(Literal::Logical(l.clone()))),
Token::Relation(r) => Some(Element::Literal(Literal::Relation(r.clone()))),
Token::Greek(g) => Some(Element::Literal(Literal::Greek(g.clone()))),
Token::Text(t) => {
if let Some(literal) = self.parse_text(t) {
Some(Element::Literal(literal))
} else {
None
}
}
Token::Operation(op) => Some(self.parse_operation(op)),
Token::Misc(m) => Some(self.parse_misc(m)),
_ => 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 })),
_ => None,
}
}
fn parse_operation(&mut self, token: Operation) -> Element {
match token {
Operation::Sum => {
let mut sum = Sum::new();
sum.bottom = self.parse_sub();
sum.top = self.parse_pow();
Element::Special(Special::Sum(sum))
}
Operation::Prod => {
let mut prod = Prod::new();
prod.bottom = self.parse_sub();
prod.top = self.parse_pow();
Element::Special(Special::Prod(prod))
}
_ => Element::Literal(Literal::Operation(token)),
}
}
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::LatexFrac => {
self.step();
Element::Special(Special::Frac(Frac {
top: self.parse_element().unwrap().boxed(),
bottom: self.parse_element().unwrap().boxed(),
}))
}
Misc::Sqrt => {
self.step();
Element::Special(Special::Sqrt(Sqrt {
inner: self.parse_element().unwrap().boxed(),
}))
}
Misc::Root => {
self.step();
let base = self.parse_element().unwrap().boxed();
self.step();
let inner = self.parse_element().unwrap().boxed();
Element::Special(Special::Root(Root { inner, base }))
}
Misc::Int => Element::Special(Special::Integral(Integral {
bottom: self.parse_sub(),
top: self.parse_pow(),
})),
Misc::OInt => Element::Special(Special::OIntegral(OIntegral {
bottom: self.parse_sub(),
top: self.parse_pow(),
})),
_ => Element::Literal(Literal::Misc(token)),
}
}
fn parse_sub(&mut self) -> Option<Box<Element>> {
if let Some(Token::Misc(Misc::Sub)) = self.peek() {
self.step();
self.step();
if let Some(element) = self.parse_element() {
Some(element.boxed())
} else {
None
}
} else {
None
}
}
fn parse_pow(&mut self) -> Option<Box<Element>> {
if let Some(Token::Misc(Misc::Pow)) = self.peek() {
self.step();
self.step();
if let Some(element) = self.parse_element() {
Some(element.boxed())
} else {
None
}
} else {
None
}
}
}

Loading…
Cancel
Save