From 9a3606b7fb282c6ed1ee4f10c0e71f1c53b15fff Mon Sep 17 00:00:00 2001 From: Ekin Date: Fri, 24 Jun 2022 16:25:46 +0200 Subject: [PATCH 1/4] Skeloton --- server/Cargo.lock | 2 + server/Cargo.toml | 6 +- server/src/ast/mod.rs | 273 +++++++++++++++++++++++++++-- server/src/ast/parser/tests/mod.rs | 24 ++- server/src/main.rs | 3 + 5 files changed, 295 insertions(+), 13 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index c0a276d..03b1482 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -381,7 +381,9 @@ version = "0.1.0" dependencies = [ "bigdecimal", "chrono", + "lazy_static", "log 0.4.17", + "num-bigint", "parser_combinator", "ron", "serde", diff --git a/server/Cargo.toml b/server/Cargo.toml index bc51ddf..ac80cd8 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -4,11 +4,15 @@ version = "0.1.0" edition = "2021" [dependencies] +lazy_static = "1.4.0" bigdecimal = "0.3.0" +num-bigint = "0.4.3" + + chrono = "0.4.19" log = "0.4.17" ron = "0.7.0" serde = "1.0.136" simplelog = "0.12.0" websocket = { version = "0.26.4", features = ["sync"] } -parser_combinator = { git = "https://github.com/ekinimo/Kirby", branch = 'main' } \ No newline at end of file +parser_combinator = { git = "https://github.com/ekinimo/Kirby", branch = 'main' } diff --git a/server/src/ast/mod.rs b/server/src/ast/mod.rs index 48da08c..4919b9e 100644 --- a/server/src/ast/mod.rs +++ b/server/src/ast/mod.rs @@ -1,7 +1,13 @@ -use std::fmt::{Display, Formatter}; +#![feature(map_first_last)] use bigdecimal::BigDecimal; +use bigdecimal::One; +use bigdecimal::Zero; +use std::collections::BTreeMap; +use std::fmt::{Display, Formatter}; +use std::ops::*; +//use bigint::{BigInt,Sign,BigUInt}; pub mod parser; #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] @@ -34,15 +40,262 @@ pub enum SyntaxTree { } // TODO check whether necessary -// pub enum Values { -// Variable(String), -// Number(BigDecimal), -// Sum(Vec), -// Product(Vec), -// Exponent(Vec), -// AddInv(Box), -// MulInv(Box), -// } + +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub enum Values { + Number(BigDecimal), + Variable(String), + Sum(BigDecimal, BTreeMap), + Product(BigDecimal, BTreeMap), + Exponent(Box<(Values, Values)>), +} + +impl From for Values { + fn from(node: LocalizedSyntaxNode) -> Values { + match node.tree { + SyntaxTree::Variable(value) => Values::Variable(value), + SyntaxTree::Number(value) => Values::Number(value), + SyntaxTree::Sum(box left, box right) => Values::from(left).add(right.into()), + SyntaxTree::Product(box left, box right) => Values::from(left).mul(right.into()), + SyntaxTree::Exponent(box left, box right) => Values::from(left).exp(right.into()), + SyntaxTree::Subtraction(box left, box right) => Values::from(left) + .add(Values::from(right)) + .mul(Values::Number(BigDecimal::from(-1))), + SyntaxTree::Division(box left, box right) => Values::from(left) + .mul(Values::from(right).exp(Values::Number(BigDecimal::from(-1)))), + SyntaxTree::Negation(box value) => { + Values::from(value).mul(Values::Number(BigDecimal::from(-1))) + } + } + } +} + +impl Display for Values { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Values::Variable(value) => write!(f, "{}", value), + Values::Number(value) => write!(f, "{}", value), + Values::Sum(constant, vmap) => { + write!(f, "( {constant} ").unwrap(); + for (k, v) in vmap { + write!(f, "+ {v} * {k} ").unwrap(); + } + write!(f, ")") + } + Values::Product(constant, vmap) => { + write!(f, "( {constant} ").unwrap(); + for (k, v) in vmap { + write!(f, "* {k} ^ {v} ").unwrap(); + } + write!(f, ")") + } + Values::Exponent(box (left, right)) => write!(f, "({} ^ {})", left, right), + } + } +} +//const one : BigDecimal = BigDecimal::from(1); + +//const two : BigDecimal = BigDecimal::from(2); + +fn exponantiate(mut x: BigDecimal, mut y: BigDecimal) -> BigDecimal { + if (&y).is_integer() { + if (&y).rem(BigDecimal::from(2)) == BigDecimal::zero() { + let n = y.half(); + + while (&y) > &n { + x = x.square(); + y -= BigDecimal::one(); + } + x + } else { + let n = (y.clone() - BigDecimal::one()).half(); + let m = x.clone(); + while (&y) > &n { + x = x.square(); + y -= BigDecimal::one(); + } + x * m + } + } else { + panic!("not implemented yet") + } +} + +impl Values { + // fn entry_adder( + // mut map: BTreeMap, + // pair: (&Values, &BigDecimal), + // ) -> BTreeMap { + // let (key, value) = pair; + // map.entry(key.to_owned()) + // .and_modify(|x| *x += value) + // .or_insert(value.to_owned()); + // map + // } + + fn entry_adder( + mut map: BTreeMap, + pair: (&Values, &BigDecimal), + fun: F, + ) -> BTreeMap + where + F: Fn(&mut BigDecimal, BigDecimal), + { + let (key, value) = pair; + map.entry(key.to_owned()) + .and_modify(|x| fun(x, value.to_owned())) + .or_insert(value.to_owned()); + map + } + + fn const_folder( + mut map: BTreeMap, + value: BigDecimal, + fun: F, + ) -> BTreeMap + where + F: Fn(BigDecimal, BigDecimal) -> BigDecimal, + { + match map.pop_first().unwrap() { + (Values::Number(v1), v2) => map.insert(Values::Number(fun(v1, value)), v2), + (v1, v2) => map.insert(v1, v2), + }; + map + } + + fn add(self, other: Values) -> Values { + let zero: BigDecimal = BigDecimal::from(0); + let one: BigDecimal = BigDecimal::from(1); + let two: BigDecimal = BigDecimal::from(2); + match (self, other) { + (Values::Number(x), other) | (other, Values::Number(x)) if x == zero => other, + (Values::Number(x), Values::Number(y)) => Values::Number(x + y), + (Values::Sum(cx, x), Values::Number(y)) | (Values::Number(y), Values::Sum(cx, x)) => { + Values::Sum(cx + y, x) + } + + (Values::Sum(cx, x), Values::Sum(cy, y)) => Values::Sum( + cx + cy, + x.iter().chain(y.iter()).fold(BTreeMap::new(), |a, b| { + Self::entry_adder(a, b, BigDecimal::add_assign) + }), + ), + (Values::Sum(cx, x), Values::Product(cy, y)) + | (Values::Product(cy, y), Values::Sum(cx, x)) => Values::Sum( + cx, + Self::entry_adder( + x, + (&Values::Product(BigDecimal::one(), y), &cy), + BigDecimal::add_assign, + ), + ), + + (Values::Sum(cx, x), other) | (other, Values::Sum(cx, x)) => Values::Sum( + cx, + Self::entry_adder(x, (&other, &one), BigDecimal::add_assign), + ), + + (otherleft, otherright) if otherleft == otherright => { + Values::Sum(BigDecimal::zero(), BTreeMap::from([(otherleft, two)])) + } + (otherleft, otherright) => Values::Sum( + BigDecimal::zero(), + BTreeMap::from([(otherleft, one.clone()), (otherright, one)]), + ), + } + } + fn mul(self, other: Values) -> Values { + let zero: BigDecimal = BigDecimal::from(0); + let one: BigDecimal = BigDecimal::from(1); + let two: BigDecimal = BigDecimal::from(2); + //todo!(); + match (self, other) { + (Values::Number(x), _other) | (_other, Values::Number(x)) if x == zero => { + Values::Number(zero) + } + (Values::Number(x), other) | (other, Values::Number(x)) if x == one => other, + (Values::Number(x), Values::Product(xz, z)) + | (Values::Product(xz, z), Values::Number(x)) => Values::Product(xz * x, z), + (Values::Number(x), Values::Number(y)) => Values::Number(x * y), + (Values::Number(x), other) | (other, Values::Number(x)) => { + Values::Product(x, BTreeMap::from([(other, one.clone())])) + } + + (Values::Exponent(box (a, b)), Values::Exponent(box (c, d))) => { + if a == c { + a.exp(b.add(d)) + } else if b == d { + a.mul(c).exp(d) + } else { + Values::Product( + BigDecimal::one(), + BTreeMap::from([(a.exp(b), one.clone()), (c.exp(d), one)]), + ) + } + } + (z, Values::Exponent(box (x, y))) | (Values::Exponent(box (x, y)), z) => { + if x == z { + x.exp(y.add(Values::Number(one))) + } else { + Values::Product( + BigDecimal::one(), + BTreeMap::from([(z, one.clone()), (x.exp(y), one)]), + ) + } + } + + (Values::Sum(cx, x), Values::Sum(cy, y)) => y + .iter() + .flat_map(|(y_val, y_key)| { + x.iter().map(move |(x_val, x_key)| { + x_val + .clone() + .mul(y_val.clone()) + .mul(Values::Number(x_key * y_key.clone())) + }) + }) + .fold(Values::Number(cx * cy), |x: Values, y: Values| x.add(y)), + (Values::Sum(cx, x), other) | (other, Values::Sum(cx, x)) => { + let mut ret = Values::Number(cx); + for (k, v) in x { + ret = ret.add(k.mul(other.clone()).mul(Values::Number(v))); + } + ret + } + (Values::Product(cx, x), Values::Product(cy, y)) => Values::Product( + cx * cy, + x.iter().chain(y.iter()).fold(BTreeMap::new(), |a, b| { + Self::entry_adder(a, b, BigDecimal::mul_assign) + }), + ), + (Values::Product(cx, x), other) | (other, Values::Product(cx, x)) => Values::Product( + cx, + Self::entry_adder(x, (&other, &one), BigDecimal::mul_assign), + ), + + (otherleft, otherright) => { + if otherleft == otherright { + Values::Product(BigDecimal::one(), BTreeMap::from([(otherleft, two)])) + } else { + Values::Product( + BigDecimal::one(), + BTreeMap::from([(otherleft, one.clone()), (otherright, one)]), + ) + } + } + } + } + fn exp(self, other: Values) -> Values { + match (self, other) { + (Values::Number(x), _) if x == BigDecimal::zero() => Values::Number(BigDecimal::zero()), + (_, Values::Number(x)) if x == BigDecimal::zero() => Values::Number(BigDecimal::one()), + (Values::Number(x), _) if x == BigDecimal::one() => Values::Number(BigDecimal::one()), + (other, Values::Number(x)) if x == BigDecimal::one() => other, + (Values::Number(x), Values::Number(y)) => Values::Number(exponantiate(x, y)), + (otherleft, otherright) => Values::Exponent(Box::new((otherleft, otherright))), + } + } +} #[derive(Clone, Debug, Eq, PartialEq)] pub struct LocalizedSyntaxNode { diff --git a/server/src/ast/parser/tests/mod.rs b/server/src/ast/parser/tests/mod.rs index 360f436..573283a 100644 --- a/server/src/ast/parser/tests/mod.rs +++ b/server/src/ast/parser/tests/mod.rs @@ -109,7 +109,7 @@ mod atoms { use crate::ast::parser::parse; use crate::ast::parser::tests::number; use crate::ast::Localization; - + #[test] fn integer() { let result = parse("123;".to_string()); @@ -169,7 +169,8 @@ mod add { use crate::ast::parser::parse; use crate::ast::parser::tests::number; use crate::ast::Localization; - + use crate::ast::Values; + use std::fmt::Write; #[test] fn add_two_integers() { let result = parse("123 + 456".to_string()); @@ -179,6 +180,16 @@ mod add { expected.assert_matches(result); } + #[test] + fn add_two_variables_and_convert_to_values() { + let result : Values = parse("x + x".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 2 * x )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + #[test] fn add_three_integers() { let result = parse("123 + 456 + 789".to_string()); @@ -187,6 +198,15 @@ mod add { expected.assert_matches(result); } + #[test] + fn add_two_variables_and_convert_to_values2() { + let result : Values = parse("(x+y)*(x-y) ".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + x + x ^ 2 )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } #[test] fn add_with_missing_first_summand() { diff --git a/server/src/main.rs b/server/src/main.rs index d705961..24137dd 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,3 +1,6 @@ +#![feature(map_first_last)] +#![feature(box_patterns)] +#![feature(type_ascription)] use std::fs::File; use std::thread; use std::thread::sleep; From 1cbce72435d83503650e40dac4a0912f4a8900b7 Mon Sep 17 00:00:00 2001 From: Ekin Date: Sun, 26 Jun 2022 05:13:24 +0200 Subject: [PATCH 2/4] some fixes and tests --- server/src/ast/mod.rs | 178 ++++++++++++++++++++++++++--- server/src/ast/parser/tests/mod.rs | 18 --- 2 files changed, 165 insertions(+), 31 deletions(-) diff --git a/server/src/ast/mod.rs b/server/src/ast/mod.rs index 4919b9e..8851253 100644 --- a/server/src/ast/mod.rs +++ b/server/src/ast/mod.rs @@ -59,8 +59,8 @@ impl From for Values { SyntaxTree::Product(box left, box right) => Values::from(left).mul(right.into()), SyntaxTree::Exponent(box left, box right) => Values::from(left).exp(right.into()), SyntaxTree::Subtraction(box left, box right) => Values::from(left) - .add(Values::from(right)) - .mul(Values::Number(BigDecimal::from(-1))), + .add(Values::from(right).mul(Values::Number(BigDecimal::from(-1)))), + SyntaxTree::Division(box left, box right) => Values::from(left) .mul(Values::from(right).exp(Values::Number(BigDecimal::from(-1)))), SyntaxTree::Negation(box value) => { @@ -168,32 +168,72 @@ impl Values { let one: BigDecimal = BigDecimal::from(1); let two: BigDecimal = BigDecimal::from(2); match (self, other) { - (Values::Number(x), other) | (other, Values::Number(x)) if x == zero => other, - (Values::Number(x), Values::Number(y)) => Values::Number(x + y), + (Values::Number(x), other) | (other, Values::Number(x)) if x == zero => {println!("add zero {other}") ;other}, + (Values::Number(x), Values::Number(y)) => {println!("add num num {x} {y}") ;Values::Number(x + y)}, (Values::Sum(cx, x), Values::Number(y)) | (Values::Number(y), Values::Sum(cx, x)) => { + println!("add sum num {:?} {:?} {:?} ",cx, x ,y) ; Values::Sum(cx + y, x) } - (Values::Sum(cx, x), Values::Sum(cy, y)) => Values::Sum( + (Values::Sum(cx, x), Values::Sum(cy, y)) => { + println!("add sum sum {:?} {:?} {:?} {:?}",cx, x , cy ,y) ; + Values::Sum( cx + cy, x.iter().chain(y.iter()).fold(BTreeMap::new(), |a, b| { - Self::entry_adder(a, b, BigDecimal::add_assign) + Self::entry_adder(a, b, BigDecimal::add_assign ) }), - ), + ) + }, + (Values::Sum(cx, x), Values::Product(cy, mut y)) + | (Values::Product(cy, mut y), Values::Sum(cx, x)) if y.len() == 1 => { + println!("add sum prod len 1 {:?} {:?} {:?} {:?}",cx, x , cy ,y) ; + if let Some((mut key, val)) = y.pop_first() { + key = key.exp(Values::Number(val)); + Values::Sum(cx,Self::entry_adder(x, (&key, &cy), BigDecimal::add_assign )) + } + else{unreachable!()} + + }, (Values::Sum(cx, x), Values::Product(cy, y)) - | (Values::Product(cy, y), Values::Sum(cx, x)) => Values::Sum( + | (Values::Product(cy, y), Values::Sum(cx, x)) => { + println!("add sum prod {:?} {:?} {:?} {:?}",cx, x , cy ,y) ; + Values::Sum( cx, Self::entry_adder( x, (&Values::Product(BigDecimal::one(), y), &cy), BigDecimal::add_assign, ), - ), + )}, - (Values::Sum(cx, x), other) | (other, Values::Sum(cx, x)) => Values::Sum( + (Values::Sum(cx, x), other) | (other, Values::Sum(cx, x)) => { + println!("add sum other {:?} {:?} {:?} ",cx, x , other) ; + Values::Sum( cx, Self::entry_adder(x, (&other, &one), BigDecimal::add_assign), - ), + )}, + + (Values::Product(cx, mut x), Values::Product(cy, mut y)) | (Values::Product(cy, mut y), Values::Product(cx, mut x)) if x == y => { + + Values::Sum(zero, BTreeMap::from([(Values::Product(one,x), cx+cy)])) + }, + + (Values::Product(cx, mut x), other) | (other, Values::Product(cx, mut x)) => { + //println!("add sum other {:?} {:?} {:?} ",cx, x , other) ; + let map = BTreeMap::from([(other, one.clone())]); + if x.len()==1{ + if let Some((mut key, val)) = x.pop_first() { + key = key.exp(Values::Number(val)); + Values::Sum(zero,Self::entry_adder(map, (&key, &cx), BigDecimal::add_assign )) + } + else{unreachable!()} + }else{ + + Values::Sum( + zero, + Self::entry_adder(map, (&Values::Product(one,x), &cx), BigDecimal::add_assign), + )} + }, (otherleft, otherright) if otherleft == otherright => { Values::Sum(BigDecimal::zero(), BTreeMap::from([(otherleft, two)])) @@ -265,12 +305,12 @@ impl Values { (Values::Product(cx, x), Values::Product(cy, y)) => Values::Product( cx * cy, x.iter().chain(y.iter()).fold(BTreeMap::new(), |a, b| { - Self::entry_adder(a, b, BigDecimal::mul_assign) + Self::entry_adder(a, b, BigDecimal::add_assign) }), ), (Values::Product(cx, x), other) | (other, Values::Product(cx, x)) => Values::Product( cx, - Self::entry_adder(x, (&other, &one), BigDecimal::mul_assign), + Self::entry_adder(x, (&other, &one), BigDecimal::add_assign), ), (otherleft, otherright) => { @@ -413,4 +453,116 @@ mod tests { assert_eq!(expected, format!("{}", under_test)); } + + + + use bigdecimal::{BigDecimal, FromPrimitive}; + + use crate::ast::parser::parse; + use crate::ast::Localization; + use std::fmt::Write; + + + #[test] + fn add_two_variables_and_convert_to_values() { + let result : Values = parse("x + x".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 2 * x )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + #[test] + fn add_several_variables_and_convert_to_values() { + let result : Values = parse("x+y+3+y+2*x+y+2-4*y".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 5 + 3 * x + -1 * y )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + #[test] + fn mul_several_variables_and_convert_to_values() { + let result : Values = parse("x*x*y*y ".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 1 * x ^ 2 * y ^ 2 )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + #[test] + fn mul_two_variables_add_and_convert_to_values() { + let result : Values = parse("x*y + y*x + 2*y*x + 3*x*y".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 7 * ( 1 * x ^ 1 * y ^ 1 ) )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + #[test] + fn mul_several_variables_and_convert_to_valuesa() { + let result : Values = parse("x*y * y*x * 2*y*x * 3*x*y".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 6 * x ^ 4 * y ^ 4 )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + #[test] + fn mul_several_variables_and_add_and_convert_to_values2() { + let result : Values = parse("x*y * y*x * 2*y*x * 3*x*y + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 126 * ( 1 * x ^ 4 * y ^ 4 ) )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + #[test] + fn mul_several_variables_and_add_and_convert_to_values3() { + let result : Values = parse("x*y * y*x * y*2*x * x*y*3 + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 126 * ( 1 * x ^ 4 * y ^ 4 ) )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + + #[test] + fn square_of_sum() { + let result : Values = parse("(x+y)*(x+y)".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 2 * ( 1 * x ^ 1 * y ^ 1 ) + 1 * (x ^ 2) + 1 * (y ^ 2) )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + #[test] + fn square_of_diff() { + let result : Values = parse("(x+y)*(x-y)".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 0 * ( 1 * x ^ 1 * y ^ 1 ) + 1 * (x ^ 2) + -1 * (y ^ 2) )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + #[test] + fn cube_of_sum() { + let result : Values = parse("(x+y)*(x+y)*(x+y)".to_string()).unwrap().pop().unwrap().into(); + + let expected = "( 0 + 3 * ( 1 * x ^ 2 * y ^ 1 ) + 3 * ( 1 * x ^ 1 * y ^ 2 ) + 1 * (x ^ 3) + 1 * (y ^ 3) )"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected,result_text) + } + + + } diff --git a/server/src/ast/parser/tests/mod.rs b/server/src/ast/parser/tests/mod.rs index 573283a..85d2dcf 100644 --- a/server/src/ast/parser/tests/mod.rs +++ b/server/src/ast/parser/tests/mod.rs @@ -180,16 +180,6 @@ mod add { expected.assert_matches(result); } - #[test] - fn add_two_variables_and_convert_to_values() { - let result : Values = parse("x + x".to_string()).unwrap().pop().unwrap().into(); - - let expected = "( 0 + 2 * x )"; - let mut result_text = String::new(); - write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) - } - #[test] fn add_three_integers() { let result = parse("123 + 456 + 789".to_string()); @@ -198,15 +188,7 @@ mod add { expected.assert_matches(result); } - #[test] - fn add_two_variables_and_convert_to_values2() { - let result : Values = parse("(x+y)*(x-y) ".to_string()).unwrap().pop().unwrap().into(); - let expected = "( 0 + x + x ^ 2 )"; - let mut result_text = String::new(); - write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) - } #[test] fn add_with_missing_first_summand() { From 5a0d2d93b783054ec52b1e3e5ba14f948092f7ec Mon Sep 17 00:00:00 2001 From: Ekin Date: Tue, 28 Jun 2022 20:25:06 +0200 Subject: [PATCH 3/4] yeeey passing tests and some nice cosmetics --- server/src/ast/mod.rs | 414 ++++++++++++++++++++++++++++++------------ 1 file changed, 301 insertions(+), 113 deletions(-) diff --git a/server/src/ast/mod.rs b/server/src/ast/mod.rs index 8851253..894dda9 100644 --- a/server/src/ast/mod.rs +++ b/server/src/ast/mod.rs @@ -3,6 +3,7 @@ use bigdecimal::BigDecimal; use bigdecimal::One; use bigdecimal::Zero; +use std::collections::HashMap; use std::collections::BTreeMap; use std::fmt::{Display, Formatter}; @@ -60,7 +61,6 @@ impl From for Values { SyntaxTree::Exponent(box left, box right) => Values::from(left).exp(right.into()), SyntaxTree::Subtraction(box left, box right) => Values::from(left) .add(Values::from(right).mul(Values::Number(BigDecimal::from(-1)))), - SyntaxTree::Division(box left, box right) => Values::from(left) .mul(Values::from(right).exp(Values::Number(BigDecimal::from(-1)))), SyntaxTree::Negation(box value) => { @@ -72,24 +72,92 @@ impl From for Values { impl Display for Values { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let supscriptmap = HashMap::from([ + ('0', '⁰'), + ('1', '¹'), + ('2', '²'), + ('3', '³'), + ('4', '⁴'), + ('5', '⁵'), + ('6', '⁶'), + ('8', '⁸'), + ('7', '⁷'), + ('9', '⁹'), + ('-', '⁻'), + ]); match self { Values::Variable(value) => write!(f, "{}", value), Values::Number(value) => write!(f, "{}", value), Values::Sum(constant, vmap) => { - write!(f, "( {constant} ").unwrap(); - for (k, v) in vmap { - write!(f, "+ {v} * {k} ").unwrap(); + let mut vect = vec![]; + let mut map = vmap.clone(); + if constant != &BigDecimal::zero() { + vect.push(format!("{constant}")); } - write!(f, ")") + for (k, v) in map { + if v != BigDecimal::zero() && k != Values::Number(BigDecimal::zero()) { + if v == BigDecimal::one() { + vect.push(format!("{k}")); //write!(f, "+ {k} ").unwrap(); + } else if v == BigDecimal::from(-1) { + vect.push(format!(" - {k}")); //write!(f, "+ {k} ").unwrap(); + } else { + vect.push(format!("{v} {k}")); //write!(f, "+ {v} * {k} ").unwrap(); + } + } + } + + vect.reverse(); + write!(f, "{}", vect.pop().unwrap()); + vect.reverse(); + write!( + f, + "{}", + vect.iter() + .map(|x| { + if x.chars().nth(1).unwrap() == '-' { + x.to_owned() + } else { + format!(" + {x}") + } + }) + .collect::() + ) } Values::Product(constant, vmap) => { - write!(f, "( {constant} ").unwrap(); - for (k, v) in vmap { - write!(f, "* {k} ^ {v} ").unwrap(); + let mut map = vmap.clone(); + if constant == &BigDecimal::zero() { + write!(f, "0") + } else { + let mut vect = vec![]; + if constant != &BigDecimal::one() { + vect.push(format!("{constant}")); + } + for (k, v) in map { + if v == BigDecimal::zero() { + } else if v == BigDecimal::one() { + vect.push(format!("{k}")); + } else { + let elem = format!( + "{k}{}", + format!("{v}") + .chars() + .map(|x| { + let ret = x.clone(); + match supscriptmap.get(&x){ + None => ret, + Some(r) => r.to_owned() + } + + }) + .collect::() + ); + vect.push(elem); + } + } + write!(f, "{}", vect.join(" ")) } - write!(f, ")") } - Values::Exponent(box (left, right)) => write!(f, "({} ^ {})", left, right), + Values::Exponent(box (left, right)) => write!(f, "({}) ^ ({})", left, right), } } } @@ -102,7 +170,7 @@ fn exponantiate(mut x: BigDecimal, mut y: BigDecimal) -> BigDecimal { if (&y).rem(BigDecimal::from(2)) == BigDecimal::zero() { let n = y.half(); - while (&y) > &n { + while y > n { x = x.square(); y -= BigDecimal::one(); } @@ -110,7 +178,7 @@ fn exponantiate(mut x: BigDecimal, mut y: BigDecimal) -> BigDecimal { } else { let n = (y.clone() - BigDecimal::one()).half(); let m = x.clone(); - while (&y) > &n { + while y > n { x = x.square(); y -= BigDecimal::one(); } @@ -144,22 +212,7 @@ impl Values { let (key, value) = pair; map.entry(key.to_owned()) .and_modify(|x| fun(x, value.to_owned())) - .or_insert(value.to_owned()); - map - } - - fn const_folder( - mut map: BTreeMap, - value: BigDecimal, - fun: F, - ) -> BTreeMap - where - F: Fn(BigDecimal, BigDecimal) -> BigDecimal, - { - match map.pop_first().unwrap() { - (Values::Number(v1), v2) => map.insert(Values::Number(fun(v1, value)), v2), - (v1, v2) => map.insert(v1, v2), - }; + .or_insert_with(|| value.to_owned()); map } @@ -168,72 +221,105 @@ impl Values { let one: BigDecimal = BigDecimal::from(1); let two: BigDecimal = BigDecimal::from(2); match (self, other) { - (Values::Number(x), other) | (other, Values::Number(x)) if x == zero => {println!("add zero {other}") ;other}, - (Values::Number(x), Values::Number(y)) => {println!("add num num {x} {y}") ;Values::Number(x + y)}, + (Values::Number(x), other) | (other, Values::Number(x)) if x == zero => { + //println!("add zero {other}"); + other + } + (Values::Number(x), Values::Number(y)) => { + //println!("add num num {x} {y}"); + Values::Number(x + y) + } (Values::Sum(cx, x), Values::Number(y)) | (Values::Number(y), Values::Sum(cx, x)) => { - println!("add sum num {:?} {:?} {:?} ",cx, x ,y) ; + //println!("add sum num {:?} {:?} {:?} ", cx, x, y); Values::Sum(cx + y, x) } (Values::Sum(cx, x), Values::Sum(cy, y)) => { - println!("add sum sum {:?} {:?} {:?} {:?}",cx, x , cy ,y) ; + //println!("add sum sum {:?} {:?} {:?} {:?}", cx, x, cy, y); Values::Sum( - cx + cy, - x.iter().chain(y.iter()).fold(BTreeMap::new(), |a, b| { - Self::entry_adder(a, b, BigDecimal::add_assign ) - }), - ) - }, + cx + cy, + x.iter().chain(y.iter()).fold(BTreeMap::new(), |a, b| { + Self::entry_adder(a, b, BigDecimal::add_assign) + }), + ) + } (Values::Sum(cx, x), Values::Product(cy, mut y)) - | (Values::Product(cy, mut y), Values::Sum(cx, x)) if y.len() == 1 => { - println!("add sum prod len 1 {:?} {:?} {:?} {:?}",cx, x , cy ,y) ; - if let Some((mut key, val)) = y.pop_first() { - key = key.exp(Values::Number(val)); - Values::Sum(cx,Self::entry_adder(x, (&key, &cy), BigDecimal::add_assign )) - } - else{unreachable!()} - - }, + | (Values::Product(cy, mut y), Values::Sum(cx, x)) + if y.len() == 1 => + { + //println!("add sum prod len 1 {:?} {:?} {:?} {:?}", cx, x, cy, y); + if let Some((mut key, val)) = y.pop_first() { + key = key.exp(Values::Number(val)); + Values::Sum( + cx, + Self::entry_adder(x, (&key, &cy), BigDecimal::add_assign), + ) + } else { + unreachable!() + } + } (Values::Sum(cx, x), Values::Product(cy, y)) | (Values::Product(cy, y), Values::Sum(cx, x)) => { - println!("add sum prod {:?} {:?} {:?} {:?}",cx, x , cy ,y) ; - Values::Sum( - cx, - Self::entry_adder( - x, - (&Values::Product(BigDecimal::one(), y), &cy), - BigDecimal::add_assign, - ), - )}, + //println!("add sum prod {:?} {:?} {:?} {:?}", cx, x, cy, y); + //println!("Y === {:?}", y); + let res = Values::Sum( + cx, + Self::entry_adder( + x.clone(), + (&Values::Product(BigDecimal::one(), y), &cy), + BigDecimal::add_assign, + ), + ); + //println!("R === {:?}", &x); + res + } (Values::Sum(cx, x), other) | (other, Values::Sum(cx, x)) => { - println!("add sum other {:?} {:?} {:?} ",cx, x , other) ; + //println!("add sum other {:?} {:?} {:?} ", cx, x, other); Values::Sum( - cx, - Self::entry_adder(x, (&other, &one), BigDecimal::add_assign), - )}, + cx, + Self::entry_adder(x, (&other, &one), BigDecimal::add_assign), + ) + } - (Values::Product(cx, mut x), Values::Product(cy, mut y)) | (Values::Product(cy, mut y), Values::Product(cx, mut x)) if x == y => { - - Values::Sum(zero, BTreeMap::from([(Values::Product(one,x), cx+cy)])) - }, + (Values::Product(cx, x), Values::Product(cy, y)) + | (Values::Product(cy, y), Values::Product(cx, x)) + if x == y => + { + Values::Sum(zero, BTreeMap::from([(Values::Product(one, x), cx + cy)])) + } + (Values::Product(cx, x), Values::Product(cy, y)) => Values::Sum( + zero, + BTreeMap::from([ + (Values::Product(one.clone(), x), cx), + (Values::Product(one, y), cy), + ]), + ), (Values::Product(cx, mut x), other) | (other, Values::Product(cx, mut x)) => { - //println!("add sum other {:?} {:?} {:?} ",cx, x , other) ; + //println!("add product other {:?} {:?} {:?} ", cx, x, other); let map = BTreeMap::from([(other, one.clone())]); - if x.len()==1{ + if x.len() == 1 { if let Some((mut key, val)) = x.pop_first() { key = key.exp(Values::Number(val)); - Values::Sum(zero,Self::entry_adder(map, (&key, &cx), BigDecimal::add_assign )) + Values::Sum( + zero, + Self::entry_adder(map, (&key, &cx), BigDecimal::add_assign), + ) + } else { + unreachable!() } - else{unreachable!()} - }else{ - + } else { Values::Sum( - zero, - Self::entry_adder(map, (&Values::Product(one,x), &cx), BigDecimal::add_assign), - )} - }, + zero, + Self::entry_adder( + map, + (&Values::Product(one, x), &cx), + BigDecimal::add_assign, + ), + ) + } + } (otherleft, otherright) if otherleft == otherright => { Values::Sum(BigDecimal::zero(), BTreeMap::from([(otherleft, two)])) @@ -258,7 +344,7 @@ impl Values { | (Values::Product(xz, z), Values::Number(x)) => Values::Product(xz * x, z), (Values::Number(x), Values::Number(y)) => Values::Number(x * y), (Values::Number(x), other) | (other, Values::Number(x)) => { - Values::Product(x, BTreeMap::from([(other, one.clone())])) + Values::Product(x, BTreeMap::from([(other, one)])) } (Values::Exponent(box (a, b)), Values::Exponent(box (c, d))) => { @@ -276,6 +362,8 @@ impl Values { (z, Values::Exponent(box (x, y))) | (Values::Exponent(box (x, y)), z) => { if x == z { x.exp(y.add(Values::Number(one))) + } else if let Values::Number(num_val) = y { + Values::Product(BigDecimal::one(), BTreeMap::from([(z, one), (x, num_val)])) } else { Values::Product( BigDecimal::one(), @@ -332,6 +420,8 @@ impl Values { (Values::Number(x), _) if x == BigDecimal::one() => Values::Number(BigDecimal::one()), (other, Values::Number(x)) if x == BigDecimal::one() => other, (Values::Number(x), Values::Number(y)) => Values::Number(exponantiate(x, y)), + (x, Values::Number(y)) => Values::Product(BigDecimal::one(), BTreeMap::from([(x, y)])), + (Values::Exponent(box (a, b)), c) => a.exp(b.mul(c)), (otherleft, otherright) => Values::Exponent(Box::new((otherleft, otherright))), } } @@ -454,115 +544,213 @@ mod tests { assert_eq!(expected, format!("{}", under_test)); } - - use bigdecimal::{BigDecimal, FromPrimitive}; use crate::ast::parser::parse; use crate::ast::Localization; use std::fmt::Write; - #[test] fn add_two_variables_and_convert_to_values() { - let result : Values = parse("x + x".to_string()).unwrap().pop().unwrap().into(); + let result: Values = parse("x + x".to_string()).unwrap().pop().unwrap().into(); - let expected = "( 0 + 2 * x )"; + let expected = "2 x"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } #[test] fn add_several_variables_and_convert_to_values() { - let result : Values = parse("x+y+3+y+2*x+y+2-4*y".to_string()).unwrap().pop().unwrap().into(); + let result: Values = parse("x+y+3+y+2*x+y+2-4*y".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); - let expected = "( 5 + 3 * x + -1 * y )"; + let expected = "5 + 3 x - y"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } #[test] fn mul_several_variables_and_convert_to_values() { - let result : Values = parse("x*x*y*y ".to_string()).unwrap().pop().unwrap().into(); + let result: Values = parse("x*x*y*y ".to_string()).unwrap().pop().unwrap().into(); - let expected = "( 1 * x ^ 2 * y ^ 2 )"; + let expected = "x² y²"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } #[test] fn mul_two_variables_add_and_convert_to_values() { - let result : Values = parse("x*y + y*x + 2*y*x + 3*x*y".to_string()).unwrap().pop().unwrap().into(); + let result: Values = parse("x*y + y*x + 2*y*x + 3*x*y".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); - let expected = "( 0 + 7 * ( 1 * x ^ 1 * y ^ 1 ) )"; + let expected = "7 x y"; //; "7 x y";//; "( 0 + 7 * ( 1 * x ^ 1 * y ^ 1 ) )"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } #[test] fn mul_several_variables_and_convert_to_valuesa() { - let result : Values = parse("x*y * y*x * 2*y*x * 3*x*y".to_string()).unwrap().pop().unwrap().into(); + let result: Values = parse("x*y * y*x * 2*y*x * 3*x*y".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); - let expected = "( 6 * x ^ 4 * y ^ 4 )"; + let expected = "6 x⁴ y⁴"; //; "( 6 * x ^ 4 * y ^ 4 )"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } #[test] fn mul_several_variables_and_add_and_convert_to_values2() { - let result : Values = parse("x*y * y*x * 2*y*x * 3*x*y + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()).unwrap().pop().unwrap().into(); - - let expected = "( 0 + 126 * ( 1 * x ^ 4 * y ^ 4 ) )"; + let result: Values = + parse("x*y * y*x * 2*y*x * 3*x*y + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected = "126 x⁴ y⁴"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } #[test] fn mul_several_variables_and_add_and_convert_to_values3() { - let result : Values = parse("x*y * y*x * y*2*x * x*y*3 + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()).unwrap().pop().unwrap().into(); - - let expected = "( 0 + 126 * ( 1 * x ^ 4 * y ^ 4 ) )"; + let result: Values = + parse("x*y * y*x * y*2*x * x*y*3 + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected = "126 x⁴ y⁴"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } - #[test] fn square_of_sum() { - let result : Values = parse("(x+y)*(x+y)".to_string()).unwrap().pop().unwrap().into(); + let result: Values = parse("(x+y)*(x+y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); - let expected = "( 0 + 2 * ( 1 * x ^ 1 * y ^ 1 ) + 1 * (x ^ 2) + 1 * (y ^ 2) )"; + let expected = "2 x y + x² + y²"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } #[test] - fn square_of_diff() { - let result : Values = parse("(x+y)*(x-y)".to_string()).unwrap().pop().unwrap().into(); + fn diff_of_square() { + let result: Values = parse("(x+y)*(x-y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected = "x² - y²"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected, result_text) + } - let expected = "( 0 + 0 * ( 1 * x ^ 1 * y ^ 1 ) + 1 * (x ^ 2) + -1 * (y ^ 2) )"; + #[test] + fn diff_of_cubes() { + let result: Values = parse("(x-y)*(x^2+y^2+x*y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected = "x³ - y³"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } + #[test] fn cube_of_sum() { - let result : Values = parse("(x+y)*(x+y)*(x+y)".to_string()).unwrap().pop().unwrap().into(); + let result: Values = parse("(x+y)*(x+y)*(x+y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); - let expected = "( 0 + 3 * ( 1 * x ^ 2 * y ^ 1 ) + 3 * ( 1 * x ^ 1 * y ^ 2 ) + 1 * (x ^ 3) + 1 * (y ^ 3) )"; + let expected = "3 x y² + 3 x² y + x³ + y³"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); - assert_eq!(expected,result_text) + assert_eq!(expected, result_text) } - + #[test] + fn cube_of_diff() { + let result: Values = parse("(x-y)*(x-y)*(x-y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected = "3 x y² + -3 x² y + x³ - y³"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected, result_text) + } + #[test] + fn fourth_of_sum() { + let result: Values = parse("(x+y)*(x+y)*(x+y)*(x+y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected = "4 x y³ + 6 x² y² + 4 x³ y + x⁴ + y⁴"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected, result_text) + } + + #[test] + fn fifth_of_sum() { + let result: Values = parse("(x+y)*(x+y)*(x+y)*(x+y)*(x+y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected = "5 x y⁴ + 10 x² y³ + 10 x³ y² + 5 x⁴ y + x⁵ + y⁵"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected, result_text) + } + + #[test] + fn sixth_of_sum() { + let result: Values = parse("(x+y)*(x+y)*(x+y)*(x+y)*(x+y)*(x+y)".to_string()) + .unwrap() + .pop() + .unwrap() + .into(); + + let expected ="6 x y⁵ + 15 x² y⁴ + 20 x³ y³ + 15 x⁴ y² + 6 x⁵ y + x⁶ + y⁶"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected, result_text) + } } From d4c8b2e56f8ac668bba802645917539344f90838 Mon Sep 17 00:00:00 2001 From: Ekin Date: Tue, 5 Jul 2022 22:14:04 +0200 Subject: [PATCH 4/4] new parser --- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- server/src/ast/mod.rs | 486 ++++++++++++++++----- server/src/ast/parser/mod.rs | 675 ++++++++++++++++++++--------- server/src/ast/parser/tests/mod.rs | 11 +- 5 files changed, 847 insertions(+), 329 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 03b1482..7be48b2 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -595,7 +595,7 @@ dependencies = [ [[package]] name = "parser_combinator" version = "0.1.0" -source = "git+https://github.com/ekinimo/Kirby?branch=main" +source = "git+https://github.com/ekinimo/Kirby?branch=State#6f96ee06ddd3c2d77d12b8e75127dd443590a663" [[package]] name = "percent-encoding" diff --git a/server/Cargo.toml b/server/Cargo.toml index ac80cd8..4ffd205 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -15,4 +15,4 @@ ron = "0.7.0" serde = "1.0.136" simplelog = "0.12.0" websocket = { version = "0.26.4", features = ["sync"] } -parser_combinator = { git = "https://github.com/ekinimo/Kirby", branch = 'main' } +parser_combinator = { git = "https://github.com/ekinimo/Kirby", branch = 'State' } diff --git a/server/src/ast/mod.rs b/server/src/ast/mod.rs index 894dda9..4fef83a 100644 --- a/server/src/ast/mod.rs +++ b/server/src/ast/mod.rs @@ -7,6 +7,7 @@ use std::collections::HashMap; use std::collections::BTreeMap; use std::fmt::{Display, Formatter}; +use std::marker::PhantomData; use std::ops::*; //use bigint::{BigInt,Sign,BigUInt}; pub mod parser; @@ -27,20 +28,94 @@ impl Localization { } } + + #[derive(Clone, Debug, Eq, PartialEq)] -pub enum SyntaxTree { - Variable(String), - Number(BigDecimal), - Sum(Box, Box), - Product(Box, Box), - Exponent(Box, Box), +pub struct Node{ + value:T, + location:(Localization,Localization), + phantom:PhantomData, +} + + + +impl Node{ + + fn new(starts: Localization,ends:Localization, tree: T) -> Self { + Self {value:tree,location:(starts,ends),phantom:PhantomData } + } + fn starts_at(&mut self,pos:Localization){ + self.location.0=pos + + } + fn ends_at(&mut self,pos:Localization){ + self.location.1=pos + + } + + fn at(&mut self,start:Localization,end:Localization){ + self.location=(start,end) + } + + - Subtraction(Box, Box), - Division(Box, Box), - Negation(Box), } +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EVar; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ENum; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EFun; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ESum; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EMul; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ESub; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EExp; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EDiv; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ENeg; + -// TODO check whether necessary +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EExpression; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EAtom; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct EBracketedExpression; + + + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ExpressionSyntaxTree { + Variable(Node), + Number(Node), + Fun(Node)>), + + Sum(Box>), + Product(Box>), + + Exponent(Box>), + + Subtraction(Box>), + Division(Box>), + Negation(Box>), +} + +//TODO Knuth=Bendix algo (Given x+0 = 0, x-x=0 ,.... Reduce x+x-x) +//#[derive(Clone, Debug, Eq, PartialEq)] +//pub struct UserRuleScheme(Vec<(ExpressionSyntaxTree,ExpressionSyntaxTree)>); + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum SyntaxTree { + Expression(ExpressionSyntaxTree), + //UserRule(UserRuleScheme,ExpressionSyntaxTree), +} #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub enum Values { @@ -51,23 +126,9 @@ pub enum Values { Exponent(Box<(Values, Values)>), } -impl From for Values { - fn from(node: LocalizedSyntaxNode) -> Values { - match node.tree { - SyntaxTree::Variable(value) => Values::Variable(value), - SyntaxTree::Number(value) => Values::Number(value), - SyntaxTree::Sum(box left, box right) => Values::from(left).add(right.into()), - SyntaxTree::Product(box left, box right) => Values::from(left).mul(right.into()), - SyntaxTree::Exponent(box left, box right) => Values::from(left).exp(right.into()), - SyntaxTree::Subtraction(box left, box right) => Values::from(left) - .add(Values::from(right).mul(Values::Number(BigDecimal::from(-1)))), - SyntaxTree::Division(box left, box right) => Values::from(left) - .mul(Values::from(right).exp(Values::Number(BigDecimal::from(-1)))), - SyntaxTree::Negation(box value) => { - Values::from(value).mul(Values::Number(BigDecimal::from(-1))) - } - } - } +pub struct Context { + variable_dict: HashMap, + fun_dict: HashMap, } impl Display for Values { @@ -90,7 +151,7 @@ impl Display for Values { Values::Number(value) => write!(f, "{}", value), Values::Sum(constant, vmap) => { let mut vect = vec![]; - let mut map = vmap.clone(); + let map = vmap.clone(); if constant != &BigDecimal::zero() { vect.push(format!("{constant}")); } @@ -105,8 +166,11 @@ impl Display for Values { } } } + if vect.is_empty(){ + write!(f,"0") - vect.reverse(); + }else +{ vect.reverse(); write!(f, "{}", vect.pop().unwrap()); vect.reverse(); write!( @@ -121,10 +185,10 @@ impl Display for Values { } }) .collect::() - ) + )} } Values::Product(constant, vmap) => { - let mut map = vmap.clone(); + let map = vmap.clone(); if constant == &BigDecimal::zero() { write!(f, "0") } else { @@ -143,11 +207,10 @@ impl Display for Values { .chars() .map(|x| { let ret = x.clone(); - match supscriptmap.get(&x){ + match supscriptmap.get(&x) { None => ret, - Some(r) => r.to_owned() + Some(r) => r.to_owned(), } - }) .collect::() ); @@ -264,7 +327,7 @@ impl Values { //println!("Y === {:?}", y); let res = Values::Sum( cx, - Self::entry_adder( + Self::entry_adder( x.clone(), (&Values::Product(BigDecimal::one(), y), &cy), BigDecimal::add_assign, @@ -427,83 +490,183 @@ impl Values { } } -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct LocalizedSyntaxNode { - location: Localization, - tree: SyntaxTree, + +trait Eval{ + fn eval(&self,ctx:Ctx) -> Output; } -impl LocalizedSyntaxNode { - fn new(location: Localization, tree: SyntaxTree) -> Self { - Self { location, tree } + +struct SimpleEvaluator; + +impl Eval for SyntaxTree{ + fn eval(&self, ctx: &mut Context) -> Values { + match self{ + SyntaxTree::Expression(expr) => expr.eval(ctx), + } + } +} +impl Eval for ExpressionSyntaxTree{ - fn number>(location: Localization, number: N) -> Self { - Self { - location, - tree: SyntaxTree::Number(number.into()), +fn eval(&self, ctx: &Context) -> Values { + match &self { + ExpressionSyntaxTree::Number(value) => { + Values::Number(value.value.to_owned()) + } + ExpressionSyntaxTree::Fun(value) => + + { + todo!() + + }, + + ExpressionSyntaxTree::Variable(Node{value, location:_ ,phantom:_}) => { + Values::Variable(value.to_owned()) + } + + ExpressionSyntaxTree::Sum(box Node{value:(left,right), location:_,phantom:_ }) => { + left.eval(ctx).add(right.eval(ctx)) + } + ExpressionSyntaxTree::Product(box Node{value:(left,right), location:_,phantom:_ }) => { + left.eval(ctx).mul(right.eval(ctx)) + } + ExpressionSyntaxTree::Exponent( + box Node{value:(left,right), location:_,phantom:_ } + ) => { + left.eval(ctx).exp(right.eval(ctx)) + } + ExpressionSyntaxTree::Subtraction( + box Node{value:(left,right), location:_,phantom:_ } + ) => { + left.eval(ctx).add( + right.eval(ctx) + .mul(Values::Number(BigDecimal::from(-1))), + ) + } + ExpressionSyntaxTree::Division(box Node{value:(left,right), location:_,phantom:_ }) => { + left.eval(ctx).mul( + right.eval(ctx) + .exp(Values::Number(BigDecimal::from(-1))), + ) + } + ExpressionSyntaxTree::Negation( + box Node{value:value, location:_ ,phantom:_} + ) => { + value.eval(ctx).mul(Values::Number(BigDecimal::from(-1))) + } } } - #[cfg(test)] - fn variable(location: Localization, name: String) -> Self { - Self::new(location, SyntaxTree::Variable(name)) +} + + +impl ExpressionSyntaxTree { + + + + + + + fn number(starts: Localization,ends:Localization, num: BigDecimal) -> Self { + + ExpressionSyntaxTree::Number(Node::new(starts, ends, num)) + } + + + + fn variable(starts: Localization,ends:Localization, name: String) -> Self { + ExpressionSyntaxTree::Variable(Node::new(starts, ends, name)) + + } + + fn add(starts: Localization,ends:Localization, left: Self, right: Self) -> Self { + ExpressionSyntaxTree::Sum(Box::new( + Node::new( + starts, ends,(left,right)) + ) + ) } - fn add(location: Localization, left: Self, right: Self) -> Self { - Self::new(location, SyntaxTree::Sum(Box::new(left), Box::new(right))) + fn mul(starts: Localization,ends:Localization, left: Self, right: Self) -> Self { + ExpressionSyntaxTree::Product(Box::new( + Node::new( + starts, ends,(left,right)) + ) + ) } - fn mul(location: Localization, left: Self, right: Self) -> Self { - Self::new( - location, - SyntaxTree::Product(Box::new(left), Box::new(right)), - ) + fn sub(starts: Localization,ends:Localization, left: Self, right: Self) -> Self { + ExpressionSyntaxTree::Subtraction(Box::new( + Node::new( + starts, ends,(left,right)) + ) + ) } - fn sub(location: Localization, left: Self, right: Self) -> Self { - Self::new( - location, - SyntaxTree::Subtraction(Box::new(left), Box::new(right)), - ) + fn div(starts: Localization,ends:Localization, left: Self, right: Self) -> Self { + ExpressionSyntaxTree::Division( + Box::new(Node::new( + starts, ends,(left,right)) + ) + ) } - fn div(location: Localization, left: Self, right: Self) -> Self { - Self::new( - location, - SyntaxTree::Division(Box::new(left), Box::new(right)), - ) + fn exp(starts: Localization,ends:Localization, left: Self, right: Self) -> Self { + ExpressionSyntaxTree::Exponent( + Box::new(Node::new( + starts, ends,(left,right)) + ) + ) } - fn exp(location: Localization, left: Self, right: Self) -> Self { - Self::new( - location, - SyntaxTree::Exponent(Box::new(left), Box::new(right)), - ) + fn neg(starts: Localization,ends:Localization, value: Self) -> Self + { + ExpressionSyntaxTree::Negation( + Box::new(Node::new( + starts, ends,value + ))) } - fn neg(location: Localization, value: Self) -> Self { - Self::new(location, SyntaxTree::Negation(Box::new(value))) + fn fun(starts: Localization,ends:Localization, name: String,vec: Vec) -> Self + { + ExpressionSyntaxTree::Fun( + Node::new( + starts, ends,(name,vec) + )) } + + } -impl Display for LocalizedSyntaxNode { +impl Display for SyntaxTree { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.tree) + match self { + SyntaxTree::Expression(a) => write!(f, "{a}"), + } } } -impl Display for SyntaxTree { +impl Display for ExpressionSyntaxTree { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - SyntaxTree::Variable(value) => write!(f, "{}", value), - SyntaxTree::Number(value) => write!(f, "{}", value), - SyntaxTree::Sum(left, right) => write!(f, "({} + {})", left, right), - SyntaxTree::Product(left, right) => write!(f, "({} * {})", left, right), - SyntaxTree::Exponent(left, right) => write!(f, "({} ^ {})", left, right), - SyntaxTree::Subtraction(left, right) => write!(f, "({} - {})", left, right), - SyntaxTree::Division(left, right) => write!(f, "({} / {})", left, right), - SyntaxTree::Negation(value) => write!(f, "-{}", value), + ExpressionSyntaxTree::Variable(Node{value, location:_ , phantom:_ }) => write!(f, "{}", value), + ExpressionSyntaxTree::Fun(Node{value:(name,value), location:_ , phantom:_ } + ) => write!( + f, + "{name}({})", + value + .iter() + .map(|x| format!("{x}")) + .collect::>() + .join(",") + ), + ExpressionSyntaxTree::Number(Node{value, location:_ , phantom:_ }) => write!(f, "{}", value), + ExpressionSyntaxTree::Sum(box Node{value:(left,right), location:_ , phantom:_ }) => write!(f, "({} + {})", left, right), + ExpressionSyntaxTree::Product(box Node{value:(left,right), location:_ , phantom:_ }) => write!(f, "({} * {})", left, right), + ExpressionSyntaxTree::Exponent(box Node{value:(left,right), location:_ , phantom:_ }) => write!(f, "({} ^ {})", left, right), + ExpressionSyntaxTree::Subtraction(box Node{value:(left,right), location:_ , phantom:_ }) => write!(f, "({} - {})", left, right), + ExpressionSyntaxTree::Division(box Node{value:(left,right), location:_ , phantom:_ }) => write!(f, "({} / {})", left, right), + ExpressionSyntaxTree::Negation(box Node{value, location:_ , phantom:_ }) => write!(f, "-{}", value), } } } @@ -514,24 +677,24 @@ mod tests { #[test] fn display() { - let under_test = LocalizedSyntaxNode::neg( - Localization::new(), - LocalizedSyntaxNode::add( - Localization::new(), - LocalizedSyntaxNode::number(Localization::new(), 1), - LocalizedSyntaxNode::mul( - Localization::new(), - LocalizedSyntaxNode::number(Localization::new(), 2), - LocalizedSyntaxNode::exp( - Localization::new(), - LocalizedSyntaxNode::number(Localization::new(), 3), - LocalizedSyntaxNode::sub( - Localization::new(), - LocalizedSyntaxNode::number(Localization::new(), 4), - LocalizedSyntaxNode::div( - Localization::new(), - LocalizedSyntaxNode::number(Localization::new(), 5), - LocalizedSyntaxNode::variable(Localization::new(), "x".to_string()), + let under_test = ExpressionSyntaxTree::neg( + Localization::new(),Localization::new(), + ExpressionSyntaxTree::add( + Localization::new(),Localization::new(), + ExpressionSyntaxTree::number(Localization::new(),Localization::new(), BigDecimal::from(1)), + ExpressionSyntaxTree::mul( + Localization::new(),Localization::new(), + ExpressionSyntaxTree::number(Localization::new(),Localization::new(), BigDecimal::from(2)), + ExpressionSyntaxTree::exp( + Localization::new(),Localization::new(), + ExpressionSyntaxTree::number(Localization::new(),Localization::new(), BigDecimal::from(3)), + ExpressionSyntaxTree::sub( + Localization::new(),Localization::new(), + ExpressionSyntaxTree::number(Localization::new(),Localization::new(), BigDecimal::from(4)), + ExpressionSyntaxTree::div( + Localization::new(),Localization::new(), + ExpressionSyntaxTree::number(Localization::new(), Localization::new(),BigDecimal::from(5)), + ExpressionSyntaxTree::variable(Localization::new(), Localization::new(),"x".to_string()), ), ), ), @@ -552,7 +715,15 @@ mod tests { #[test] fn add_two_variables_and_convert_to_values() { - let result: Values = parse("x + x".to_string()).unwrap().pop().unwrap().into(); + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; + let result: Values = parse("x + x".to_string()) + .unwrap() + .pop() + .unwrap() + .eval(&mut ctx); let expected = "2 x"; let mut result_text = String::new(); @@ -562,11 +733,15 @@ mod tests { #[test] fn add_several_variables_and_convert_to_values() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("x+y+3+y+2*x+y+2-4*y".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "5 + 3 x - y"; let mut result_text = String::new(); @@ -576,7 +751,15 @@ mod tests { #[test] fn mul_several_variables_and_convert_to_values() { - let result: Values = parse("x*x*y*y ".to_string()).unwrap().pop().unwrap().into(); + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; + let result: Values = parse("x*x*y*y ".to_string()) + .unwrap() + .pop() + .unwrap() + .eval(&mut ctx); let expected = "x² y²"; let mut result_text = String::new(); @@ -586,11 +769,15 @@ mod tests { #[test] fn mul_two_variables_add_and_convert_to_values() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("x*y + y*x + 2*y*x + 3*x*y".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "7 x y"; //; "7 x y";//; "( 0 + 7 * ( 1 * x ^ 1 * y ^ 1 ) )"; let mut result_text = String::new(); @@ -600,11 +787,15 @@ mod tests { #[test] fn mul_several_variables_and_convert_to_valuesa() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("x*y * y*x * 2*y*x * 3*x*y".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "6 x⁴ y⁴"; //; "( 6 * x ^ 4 * y ^ 4 )"; let mut result_text = String::new(); @@ -614,12 +805,17 @@ mod tests { #[test] fn mul_several_variables_and_add_and_convert_to_values2() { + + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("x*y * y*x * 2*y*x * 3*x*y + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "126 x⁴ y⁴"; let mut result_text = String::new(); @@ -629,12 +825,16 @@ mod tests { #[test] fn mul_several_variables_and_add_and_convert_to_values3() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("x*y * y*x * y*2*x * x*y*3 + 5*x*y * 4*y*x * 2*y*x * 3*x*y".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "126 x⁴ y⁴"; let mut result_text = String::new(); @@ -644,11 +844,15 @@ mod tests { #[test] fn square_of_sum() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x+y)*(x+y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "2 x y + x² + y²"; let mut result_text = String::new(); @@ -656,13 +860,35 @@ mod tests { assert_eq!(expected, result_text) } + #[test] + fn for_ranja() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; + let result: Values = parse("(x-y)*(x+y)+(y-x)*(x+y)".to_string()) + .unwrap() + .pop() + .unwrap() + .eval(&mut ctx); + + let expected = "x² - y²"; + let mut result_text = String::new(); + write!(result_text, "{result}").unwrap(); + assert_eq!(expected, result_text) + } + #[test] fn diff_of_square() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x+y)*(x-y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "x² - y²"; let mut result_text = String::new(); @@ -672,11 +898,15 @@ mod tests { #[test] fn diff_of_cubes() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x-y)*(x^2+y^2+x*y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "x³ - y³"; let mut result_text = String::new(); @@ -686,11 +916,15 @@ mod tests { #[test] fn cube_of_sum() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x+y)*(x+y)*(x+y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "3 x y² + 3 x² y + x³ + y³"; let mut result_text = String::new(); @@ -700,11 +934,15 @@ mod tests { #[test] fn cube_of_diff() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x-y)*(x-y)*(x-y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "3 x y² + -3 x² y + x³ - y³"; let mut result_text = String::new(); @@ -714,11 +952,15 @@ mod tests { #[test] fn fourth_of_sum() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x+y)*(x+y)*(x+y)*(x+y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "4 x y³ + 6 x² y² + 4 x³ y + x⁴ + y⁴"; let mut result_text = String::new(); @@ -728,11 +970,15 @@ mod tests { #[test] fn fifth_of_sum() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x+y)*(x+y)*(x+y)*(x+y)*(x+y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); let expected = "5 x y⁴ + 10 x² y³ + 10 x³ y² + 5 x⁴ y + x⁵ + y⁵"; let mut result_text = String::new(); @@ -742,13 +988,17 @@ mod tests { #[test] fn sixth_of_sum() { + let mut ctx = Context { + variable_dict: HashMap::new(), + fun_dict: HashMap::new(), + }; let result: Values = parse("(x+y)*(x+y)*(x+y)*(x+y)*(x+y)*(x+y)".to_string()) .unwrap() .pop() .unwrap() - .into(); + .eval(&mut ctx); - let expected ="6 x y⁵ + 15 x² y⁴ + 20 x³ y³ + 15 x⁴ y² + 6 x⁵ y + x⁶ + y⁶"; + let expected = "6 x y⁵ + 15 x² y⁴ + 20 x³ y³ + 15 x⁴ y² + 6 x⁵ y + x⁶ + y⁶"; let mut result_text = String::new(); write!(result_text, "{result}").unwrap(); assert_eq!(expected, result_text) diff --git a/server/src/ast/parser/mod.rs b/server/src/ast/parser/mod.rs index f211ad6..ddd6990 100644 --- a/server/src/ast/parser/mod.rs +++ b/server/src/ast/parser/mod.rs @@ -14,223 +14,513 @@ use parser_combinator::*; use error::ErrorMessage; +use crate::ast::ExpressionSyntaxTree; use crate::ast::Localization; -use crate::ast::LocalizedSyntaxNode; +//use crate::ast::LocalizedSyntaxNode; +use crate::ast::Node; use crate::ast::SyntaxTree; use crate::most_important_of; +use super::EAtom; +use super::EBracketedExpression; +use super::EDiv; +use super::EExp; +use super::EExpression; +use super::EFun; +use super::EMul; +use super::ENeg; +use super::ENum; +use super::ESub; +use super::ESum; +use super::EVar; + mod error; #[cfg(test)] mod tests; -type ParseResult<'a> = - parser_combinator::ParseResult<'a, CharWrapper<'a>, LocalizedSyntaxNode, ErrorMessage>; - #[derive(Clone, Debug)] -struct CharWrapper<'a> { - chars: Chars<'a>, - start: Localization, - end: Localization, +struct State{ + start:Localization, + end:Localization, + } -impl<'a> CharWrapper<'a> { - fn new(chars: Chars<'a>) -> CharWrapper<'a> { - Self { - chars, - start: Localization::new(), - end: Localization::new(), - } - } +trait Parsable<'a,T> where + + T:Parse<'a,Chars<'a>,State,ExpressionSyntaxTree,ErrorMessage> +{ + + fn parse(self,s:State) -> ParseResult<'a>; } -impl<'a> Iterator for CharWrapper<'a> { - type Item = char; - fn next(&mut self) -> Option { - self.start = self.end; - self.end.column += 1; - let next = self.chars.next(); - if next == Some('\n') { - self.end.line += 1; - self.end.column = 0; - } - next +impl <'a> Parsable<'a,EExpression> for Chars<'a> where +{ + fn parse(self,s:State)-> ParseResult<'a> { + EExpression.parse(self, s) } } -trait Operator { - fn parser<'a>() -> Parser<'a, CharWrapper<'a>, CharWrapper<'a>, ErrorMessage>; - - fn combine( - operator: CharWrapper, - lhs: LocalizedSyntaxNode, - rhs: LocalizedSyntaxNode, - ) -> LocalizedSyntaxNode; +impl <'a> Parsable<'a,EExpression> for &'a str where +{ + fn parse(self,s:State)-> ParseResult<'a> { + EExpression.parse(self.chars(), s) + } } -struct PlusAndMinus; -impl Operator for PlusAndMinus { - fn parser<'a>() -> Parser<'a, CharWrapper<'a>, CharWrapper<'a>, ErrorMessage> { - match_literal(CharWrapper::new("+".chars())) - .or_else(match_literal(CharWrapper::new("-".chars()))) - .with_error(|_, input: CharWrapper| { - ErrorMessage::term_failed(format!( - "expected operator + or -, got {}", - input.chars.collect::() - )) - }) - .peek_and_transform(|mut x, y| { - x.end = y.start; - x - }) +impl State{ + fn new() ->State { + State{start:Localization::new(),end:Localization::new()} } - fn combine( - operator: CharWrapper, - lhs: LocalizedSyntaxNode, - rhs: LocalizedSyntaxNode, - ) -> LocalizedSyntaxNode { - let op = operator.chars.collect::(); - match &*op { - "+" => LocalizedSyntaxNode::add(operator.end, lhs, rhs), - "-" => LocalizedSyntaxNode::sub(operator.end, lhs, rhs), - _ => unreachable!("{}", op), + fn transit_generator<'a>(n:usize,m:usize) -> impl Fn(State) -> State{ + move |state: State| State { + start: state.end, + end: Localization { line: state.end.line+n, column: state.end.column+m }, } } + } -struct MulAndDiv; +fn state_trans(x:State)->State{x} -impl Operator for MulAndDiv { - fn parser<'a>() -> Parser<'a, CharWrapper<'a>, CharWrapper<'a>, ErrorMessage> { - match_literal(CharWrapper::new("*".chars())) - .or_else(match_literal(CharWrapper::new("/".chars()))) - .with_error(|_, input: CharWrapper| { - ErrorMessage::term_failed(format!( - "expected operator + or -, got {}", - input.chars.collect::() - )) - }) - .peek_and_transform(|mut x, y| { - x.end = y.start; - x - }) +type ParseResult<'a> = + Result<(ExpressionSyntaxTree, State, Chars<'a>), ErrorMessage>; + +pub fn parse(input: String) -> Result, ErrorMessage> { + todo!() +} + +impl<'a> Parse<'a, Chars<'a>, State,ExpressionSyntaxTree, ErrorMessage> for ExpressionSyntaxTree { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + todo!() } +} - fn combine( - operator: CharWrapper, - lhs: LocalizedSyntaxNode, - rhs: LocalizedSyntaxNode, - ) -> LocalizedSyntaxNode { - let op = operator.chars.collect::(); - match &*op { - "*" => LocalizedSyntaxNode::mul(operator.end, lhs, rhs), - "/" => LocalizedSyntaxNode::div(operator.end, lhs, rhs), - _ => unreachable!("{}", op), - } +impl <'b > Parse<'b, Chars<'b>,State, ExpressionSyntaxTree, ErrorMessage> for EVar +{ + fn parse( + &self, + input: Chars<'b>,state:State, + ) -> ParseResult<'b> { + let transformer = move |letters: Vec,curr_state:State| { + ExpressionSyntaxTree::variable( + state.end, + curr_state.end, + letters.iter().collect(), + ) + }; + + match_anything(State::transit_generator(1, 0)) + .validate( + |character: &char| character.is_alphabetic(), + "alphabetic character".to_string(), + ) + .one_or_more() + .transform_with_state(transformer) + .with_error(|err, input| ErrorMessage::new(err, 0, Localization::new())) + .parse(input,state) } } -pub fn parse(input: String) -> Result, ErrorMessage> { - debug!("parsing {input}"); +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for ENum { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let to_integer = |characters: Vec| { + characters + .iter() + .fold(String::new(), |mut result, character| { + result.push(*character); + result + }) + }; - let (result, leftover) = parse_expression - .separated_by(match_character(';')) - .with_error(|err, _| { - err.fold(identity, |err2| { - err2.fold(ErrorMessage::forgot_comma, identity) - }) - }) - .with_error(|error, _| error.map_message(|message| format!("Syntax Error: {}", message))) - .transform(move |(first, rest)| { - let mut result = vec![first]; - for (_, fragment) in rest { - result.push(fragment); - } - result - }) - .skip(whitespace) - .skip(semicolon) - .parse(CharWrapper::new(input.chars()))?; + let parse_natural_numbers = match_anything(State::transit_generator(1, 0)) + .validate( + |character: &char| character.is_numeric(), + "numeric character".to_string(), + ) + .one_or_more() + .transform(to_integer); - let leftover_string: String = leftover.chars.collect(); - if !leftover_string.is_empty() { - return Err(ErrorMessage::leftover(leftover_string, leftover.end)); + let parse_natural_numbers_num = match_anything(State::transit_generator(1, 0)) + .validate( + |character: &char| character.is_numeric(), + "numeric character".to_string(), + ) + .one_or_more() + .transform(to_integer) + .transform_with_state(move |num,curr_state| { + ExpressionSyntaxTree::number( + state.end, + curr_state.end, + BigDecimal::from_str(&*num).unwrap(), + ) + }); + + let separator_parser = match_literal(".".chars(),State::transit_generator(1, 0)) + .or_else(match_literal("e-".chars(),State::transit_generator(2, 0))) + .or_else(match_literal("e".chars(),State::transit_generator(1, 0))) + .with_error(|_, input| { + format!( + "expected decimal separator '.' or 'e', got {} ", + input.collect::(), + ) + }); + + let to_float = move |(leading, separator, fractional): (String, Chars, String),curr_state:State| { + let num = format!("{}{}{}", leading, separator.as_str(), fractional.as_str()); + ExpressionSyntaxTree::number( + state.end, + curr_state.end, + BigDecimal::from_str(&*num).unwrap(), + ) + }; + + Triple::new( + parse_natural_numbers.clone(), + separator_parser, + parse_natural_numbers, + ) + .transform_with_state(to_float) + + .with_error(|error, _| { + ErrorMessage::new( + error.fold(identity, identity, identity), + 1, + Localization::new(), + ) + }).or_else(parse_natural_numbers_num) + .with_error(|(a,b), _| { + ErrorMessage::new( + "number failed".to_string(), + 1, + Localization::new(), + )}) + .parse(input,state) } +} + +fn whitespace<'a>( + input: Chars<'a>,state:State, +) -> parser_combinator::ParseResult,State, char, ErrorMessage> { + + + let space = match_anything(State::transit_generator(1, 0)).validate( + |character: &char| character == &' ', + "alphabetic character".to_string(), + ); + let newline = match_anything(State::transit_generator(0, 1)).validate( + |character: &char| character == &'\n', + "alphabetic character".to_string(), + ); + + space + .or_else(newline) + .with_error(|(a, b), _| ErrorMessage::new("{a} {b}".to_string(),0,Localization::at(69, 420))) + .parse(input, state) - Ok(result) } -fn parse_expression(input: CharWrapper) -> ParseResult { - if !input.clone().any(|char| !char.is_whitespace()) { - return Err(ErrorMessage::empty_expression(format!( - "expected expression, got '{}'", - input.chars.collect::() - ))); +type BNode = Node; + +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for ESub { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let transformer = + move |(mut first, vec): (ExpressionSyntaxTree, Vec<(State, ExpressionSyntaxTree)>)| { + if vec.is_empty() { + first + } else { + for (curr_state, second) in vec { + first = ExpressionSyntaxTree::sub( + curr_state.start, + curr_state.end, + first, + second, + ) + } + first + } + }; + + ESum.pair( + match_literal("-".chars(),State::transit_generator(1, 0)) + .transform_with_state(|_,curr_state:State|curr_state).pair(Self).zero_or_more() + ) + .transform(transformer) + .with_error(|err, input| match err { + Either::Left(err) => err, + Either::Right(Either::Left(err)) => ErrorMessage::new(err, 1, Localization::new()), + Either::Right(Either::Right(err)) => err, + }) + .parse(input,state) } +} - let summand_and_operator_parser = - RepeatedParser::zero_or_more(Pair::new(parse_term, PlusAndMinus::parser())); +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for ESum { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let transformer = + move |(mut first, vec): (ExpressionSyntaxTree, Vec<(State, ExpressionSyntaxTree)>)| { + if vec.is_empty() { + first + } else { + for (curr_state, second) in vec { + first = ExpressionSyntaxTree::add( + curr_state.start, + curr_state.end, + first, + second, + ) + } + first + } + }; + + EMul.pair(match_literal("+".chars(), State::transit_generator(1, 0)).transform_with_state(|_,s|s).pair(Self).zero_or_more()) + .transform(transformer) + .with_error(|err, input| match err { + Either::Left(err) => err, + Either::Right(Either::Left(err)) => ErrorMessage::new(err, 1, Localization::new()), + Either::Right(Either::Right(err)) => err, + }) + .parse(input,state) + } +} - Pair::new(summand_and_operator_parser, parse_term) - .with_error(|error, _| error.fold(|inner_error| inner_error.reduce(), identity)) - .transform(|(summands, result)| combine_to_tree::(summands, result)) - .parse(input) +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for EMul { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let transformer = + move |(mut first, vec): (ExpressionSyntaxTree, Vec<(State, ExpressionSyntaxTree)>)| { + if vec.is_empty() { + first + } else { + for (curr_state, second) in vec { + first = ExpressionSyntaxTree::mul( + curr_state.start, + curr_state.end, + first, + second, + ) + } + first + } + }; + + EDiv.pair(match_literal("*".chars(), State::transit_generator(1, 0)).transform_with_state(|_,s|s).pair(Self).zero_or_more()) + .transform(transformer) + .with_error(|err, input| match err { + Either::Left(err) => err, + Either::Right(Either::Left(err)) => ErrorMessage::new(err, 1, Localization::new()), + Either::Right(Either::Right(err)) => err, + }) + .parse(input,state) + } } -fn combine_to_tree( - mut summands_and_operators: Vec<(LocalizedSyntaxNode, CharWrapper)>, - last_summand: LocalizedSyntaxNode, -) -> LocalizedSyntaxNode { - if summands_and_operators.is_empty() { - return last_summand; +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for EDiv { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let transformer = + move |(mut first, vec): (ExpressionSyntaxTree, Vec<(State, ExpressionSyntaxTree)>)| { + if vec.is_empty() { + first + } else { + for (curr, second) in vec { + first = ExpressionSyntaxTree::div( + curr.start, + curr.end, + first, + second, + ) + } + first + } + }; + + EExp.pair(match_literal("/".chars(),State::transit_generator(1, 0)).transform_with_state(|_,s|s).pair(Self).zero_or_more()) + .transform(transformer) + .with_error(|err, input| match err { + Either::Left(err) => err, + Either::Right(Either::Left(err)) => ErrorMessage::new(err, 1, Localization::new()), + Either::Right(Either::Right(err)) => err, + }) + .parse(input,state) } +} - let (second_last_summand, operator) = summands_and_operators.pop().unwrap(); +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for EExp { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let exponentiation_operator_parser = + match_literal("^".chars(), State::transit_generator(1, 0)).with_error(|_, input: Chars| { + ErrorMessage::exponentiation_failed(format!( + "expected operator ^, got {}", + input.collect::() + )) + }).transform_with_state(|_,s|s); - let lhs = combine_to_tree::(summands_and_operators, second_last_summand); + let exponent_parser = + RepeatedParser::zero_or_more(Pair::new(exponentiation_operator_parser, Self)) + .with_error(|error, _| error.reduce()); - T::combine(operator, lhs, last_summand) + Pair::new(ENeg, exponent_parser) + .transform(move |(x, y)| { + y.into_iter().fold(x, |left, (s, right)| { + ExpressionSyntaxTree::exp(s.start, s.end, left, right) + }) + }) + .with_error(|error, _| error.reduce()) + .parse(input,state) + } } -fn parse_term(input: CharWrapper) -> ParseResult { - let summand_and_operator_parser = - RepeatedParser::zero_or_more(Pair::new(parse_exponent, MulAndDiv::parser())); +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for ENeg { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let error_mapper = |(sign_error, expression_in_brackets_error), input: Chars| { + let message = format!( + "expected '-' or {}, got '{}'", + expression_in_brackets_error, + input.collect::(), + ); + + let new_message = match sign_error { + Either::Left(_) => ErrorMessage::sign_failed(message, Localization::new()), + Either::Right(message) => message, + }; + + most_important_of!(new_message, expression_in_brackets_error) + }; - Pair::new(summand_and_operator_parser, parse_exponent) - .with_error(|error, _| error.fold(|inner_error| inner_error.reduce(), identity)) - .transform(|(summands, result)| combine_to_tree::(summands, result)) - .parse(input) + let prefix_parser = match_literal("-".chars(), State::transit_generator(1, 0)) + .pair(Self) + .transform(move |(op, x)| { + ExpressionSyntaxTree::neg(Localization::new(), Localization::new(), x) + }); + + prefix_parser + .or_else(EBracketedExpression) + .with_error(error_mapper) + .skip(whitespace) + .parse(input,state) + } } -fn parse_exponent(input: CharWrapper) -> ParseResult { - let exponentiation_operator_parser = match_literal(CharWrapper::new("^".chars())) - .with_error(|_, input: CharWrapper| { - ErrorMessage::exponentiation_failed(format!( - "expected operator ^, got {}", - input.chars.collect::() - )) - }) - .peek_and_transform(|mut x, y| { - x.end = y.start; - x - }); - - let exponent_parser = - RepeatedParser::zero_or_more(Pair::new(exponentiation_operator_parser, parse_exponent)) - .with_error(|error, _| error.reduce()); - - Pair::new(parse_sign, exponent_parser) - .transform(move |(x, y)| { - y.into_iter().fold(x, |left, (op, right)| { - LocalizedSyntaxNode::exp(op.end, left, right) - }) - }) - .with_error(|error, _| error.reduce()) - .parse(input) +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for EBracketedExpression { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let error_mapper = + |(expression_in_brackets_error, atom_error), _| match expression_in_brackets_error { + Either3::Left(_) => most_important_of!( + ErrorMessage::missing_opening_parenthesis(format!("'(' or {}", atom_error)), + atom_error + ), + Either3::Middle(message) => message, + Either3::Right(_) => ErrorMessage::missing_closing_parenthesis( + "missing closing parenthesis".to_string(), + ), + }; + + Triple::new( + match_literal("(".chars(), State::transit_generator(1, 0)), + EExpression, + match_literal(")".chars(), State::transit_generator(1, 0)), + ) + .second() + .or_else(EAtom) + .with_error(error_mapper) + .parse(input,state) + } +} + +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for EAtom { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + EFun.or_else(ENum).with_error(|(err, _), _| err) + .or_else(EVar) + .with_error(|(err, _), _| err) + .skip(whitespace) + .parse(input,state) + } } +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for EExpression { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + if !input.clone().any(|char| !char.is_whitespace()) { + return Err(ErrorMessage::empty_expression(format!( + "expected expression, got '{}'", + input.collect::() + ))); + } + ESub.parse(input,state) + } +} + + +impl<'a> Parse<'a, Chars<'a>,State, ExpressionSyntaxTree, ErrorMessage> for EFun { + fn parse( + &self, + input: Chars<'a>,state:State, + ) -> ParseResult<'a> { + let tuple = Triple::new( + match_literal("(".chars(), State::transit_generator(1, 0)), + EExpression + .separated_by(match_literal(",".chars(), state_trans)) + .transform(|(x, y)| {let mut ret = vec![x];ret.extend(y.iter().map(|(a, b)| b.to_owned()));ret}), + match_literal(")".chars(), State::transit_generator(1, 0)), + ) + .second(); + + match_anything(State::transit_generator(1, 0)) + .validate( + |character: &char| character.is_alphabetic(), + "alphabetic character".to_string(), + ) + .one_or_more() + .pair(tuple).transform_with_state(move |(x, y),curr_state| + { + ExpressionSyntaxTree::fun(state.end,curr_state.end ,x.into_iter().collect(), y) + }).with_error(|_,_| ErrorMessage::new("func failed".to_string(),1,Localization::new())).parse(input,state) + } + + } + +#[test] +fn pof() { + let state = State::new(); + let a = "-f(1,x+x,2*2/4,5*(2+4))+1.2+x+y-z+c-t+1.3*1-6/6".chars().parse(state); + println!("{:?}", a); + assert!(false) +} +/* fn parse_sign(input: CharWrapper) -> ParseResult { let error_mapper = |(sign_error, expression_in_brackets_error), input: CharWrapper| { let message = format!( @@ -247,7 +537,7 @@ fn parse_sign(input: CharWrapper) -> ParseResult { most_important_of!(new_message, expression_in_brackets_error) }; - let prefix_parser = match_literal(CharWrapper::new("-".chars())) + let prefix_parser = match_literal(CharWrapper::new("-".chars()), state_trans) .pair(parse_sign) .transform(move |(op, x)| LocalizedSyntaxNode::neg(op.end, x)); @@ -255,7 +545,7 @@ fn parse_sign(input: CharWrapper) -> ParseResult { .or_else(parse_expression_in_brackets) .with_error(error_mapper) .skip(whitespace) - .parse(input) + .parse(input,state) } fn parse_expression_in_brackets(input: CharWrapper) -> ParseResult { @@ -272,14 +562,14 @@ fn parse_expression_in_brackets(input: CharWrapper) -> ParseResult { }; Triple::new( - match_literal(CharWrapper::new("(".chars())), + match_literal(CharWrapper::new("(".chars()), state_trans), parse_expression, - match_literal(CharWrapper::new(")".chars())), + match_literal(CharWrapper::new(")".chars()), state_trans), ) .second() .or_else(parse_atom) .with_error(error_mapper) - .parse(input) + .parse(input,state) } fn parse_atom(input: CharWrapper) -> ParseResult { @@ -292,18 +582,19 @@ fn parse_atom(input: CharWrapper) -> ParseResult { float_parser .or_else(integer_parser) .with_error(|_, _| ErrorMessage::atom_failed("a number".to_string())) + //.or_else(parse_function_call) .or_else(parse_identifier) .with_error(|(err, _), _| err) .skip(whitespace) - .parse(input) + .parse(input,state) } fn parse_float( input: CharWrapper, ) -> parser_combinator::ParseResult { - let separator_parser = match_literal(CharWrapper::new(".".chars())) - .or_else(match_literal(CharWrapper::new("e-".chars()))) - .or_else(match_literal(CharWrapper::new("e".chars()))) + let separator_parser = match_literal(CharWrapper::new(".".chars()), state_trans) + .or_else(match_literal(CharWrapper::new("e-".chars())), state_trans) + .or_else(match_literal(CharWrapper::new("e".chars())), state_trans) .with_error(|_, input| { format!( "expected decimal separator '.' or 'e', got {} ", @@ -324,7 +615,7 @@ fn parse_float( ) .transform(to_float) .with_error(|error, _| error.fold(identity, identity, identity)) - .parse(input) + .parse(input,state) } fn parse_natural_numbers( @@ -346,37 +637,11 @@ fn parse_natural_numbers( ) .one_or_more() .transform(to_integer) - .parse(input) -} - -fn parse_identifier(input: CharWrapper) -> ParseResult { - let transformer = move |letters: Vec| LocalizedSyntaxNode { - tree: SyntaxTree::Variable(letters.into_iter().collect()), - location: input.end, - }; - - match_anything() - .validate( - |character: &char| character.is_alphabetic(), - "alphabetic character".to_string(), - ) - .one_or_more() - .transform(transformer) - .with_error(|err, input: CharWrapper| ErrorMessage::new(err, 0, input.end)) - .parse(input) -} - -fn whitespace( - input: CharWrapper, -) -> parser_combinator::ParseResult { - match_anything() - .validate( - |character: &char| character == &' ' || character == &'\n', - "alphabetic character".to_string(), - ) - .with_error(|err, input: CharWrapper| ErrorMessage::new(err, 0, input.end)) - .parse(input) + .parse(input,state) } +/* +*/ +/* fn semicolon( input: CharWrapper, @@ -387,5 +652,7 @@ fn semicolon( "expected semicolon".to_string(), ) .with_error(|err, input: CharWrapper| ErrorMessage::new(err, 0, input.end)) - .parse(input) + .parse(input,state) } +*/ +*/ diff --git a/server/src/ast/parser/tests/mod.rs b/server/src/ast/parser/tests/mod.rs index 85d2dcf..9efc8c3 100644 --- a/server/src/ast/parser/tests/mod.rs +++ b/server/src/ast/parser/tests/mod.rs @@ -1,9 +1,9 @@ -use std::ops::{Add, Sub}; +/*use std::ops::{Add, Sub}; use bigdecimal::BigDecimal; use crate::ast::parser::error::ErrorMessage; -use crate::ast::{Localization, LocalizedSyntaxNode, SyntaxTree}; +use crate::ast::{Localization, LocalizedSyntaxNode, SyntaxTree,ExpressionSyntaxTree}; impl From<(usize, usize)> for Localization { fn from((line, column): (usize, usize)) -> Self { @@ -84,15 +84,15 @@ impl LocalizedSyntaxNode { let output = expected.node_matcher.clone(); match (&self.tree, expected.node_matcher) { - (SyntaxTree::Number(actual), NodeMatcher::Number(expected)) => { + (SyntaxTree::Expression(ExpressionSyntaxTree::Number(actual)), NodeMatcher::Number(expected)) => { assert_eq!(*actual, expected) } ( - SyntaxTree::Sum(actual_left, actual_right), + SyntaxTree::Expression(ExpressionSyntaxTree::Sum(actual_left, actual_right)), NodeMatcher::Sum(expected_left, expected_right), ) | ( - SyntaxTree::Subtraction(actual_left, actual_right), + SyntaxTree::Expression(ExpressionSyntaxTree::Subtraction(actual_left, actual_right)), NodeMatcher::Subtraction(expected_left, expected_right), ) => { actual_left.assert_matches(*expected_left); @@ -1467,3 +1467,4 @@ mod combined_operations { assert_eq!(Ok(expected), result); } } +*/