From eb5c6e99bd1331a495475aa6d7ea931861248499 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sat, 13 Apr 2019 20:04:36 +0200 Subject: [PATCH] Add flattening of operator chains when building operator tree Relates to #44 --- src/operator/mod.rs | 119 +++++++++++++++++++++++++++++++++++++++++-- src/tree/mod.rs | 3 ++ src/value/mod.rs | 4 ++ tests/integration.rs | 14 +++++ 4 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/operator/mod.rs b/src/operator/mod.rs index e0ff92d..84ca661 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -7,6 +7,10 @@ use crate::{context::Context, error::*, value::Value}; mod display; pub trait Operator: Debug + Display { + /// A numeric id to compare operator types. + // Make this a const fn once #57563 is resolved + fn id(&self) -> i32; + /// Returns the precedence of the operator. /// A high precedence means that the operator has priority to be deeper in the tree. // Make this a const fn once #57563 is resolved @@ -20,6 +24,12 @@ pub trait Operator: Debug + Display { true } + /// Returns true if chains of this operator should be flattened into one operator with many arguments. + // Make this a const fn once #57563 is resolved + fn is_flatten_chains(&self) -> bool { + false + } + /// True if this operator is a leaf, meaning it accepts no arguments. // Make this a const fn once #57563 is resolved fn is_leaf(&self) -> bool { @@ -123,6 +133,10 @@ impl FunctionIdentifier { } impl Operator for RootNode { + fn id(&self) -> i32 { + 1 + } + fn precedence(&self) -> i32 { 200 } @@ -141,6 +155,10 @@ impl Operator for RootNode { } impl Operator for Add { + fn id(&self) -> i32 { + 2 + } + fn precedence(&self) -> i32 { 95 } @@ -178,6 +196,10 @@ impl Operator for Add { } impl Operator for Sub { + fn id(&self) -> i32 { + 3 + } + fn precedence(&self) -> i32 { 95 } @@ -210,6 +232,10 @@ impl Operator for Sub { } impl Operator for Neg { + fn id(&self) -> i32 { + 4 + } + fn precedence(&self) -> i32 { 110 } @@ -236,6 +262,10 @@ impl Operator for Neg { } impl Operator for Mul { + fn id(&self) -> i32 { + 5 + } + fn precedence(&self) -> i32 { 100 } @@ -268,6 +298,10 @@ impl Operator for Mul { } impl Operator for Div { + fn id(&self) -> i32 { + 6 + } + fn precedence(&self) -> i32 { 100 } @@ -300,6 +334,10 @@ impl Operator for Div { } impl Operator for Mod { + fn id(&self) -> i32 { + 7 + } + fn precedence(&self) -> i32 { 100 } @@ -332,6 +370,10 @@ impl Operator for Mod { } impl Operator for Exp { + fn id(&self) -> i32 { + 8 + } + fn precedence(&self) -> i32 { 120 } @@ -355,6 +397,10 @@ impl Operator for Exp { } impl Operator for Eq { + fn id(&self) -> i32 { + 9 + } + fn precedence(&self) -> i32 { 80 } @@ -375,6 +421,10 @@ impl Operator for Eq { } impl Operator for Neq { + fn id(&self) -> i32 { + 10 + } + fn precedence(&self) -> i32 { 80 } @@ -395,6 +445,10 @@ impl Operator for Neq { } impl Operator for Gt { + fn id(&self) -> i32 { + 11 + } + fn precedence(&self) -> i32 { 80 } @@ -431,6 +485,10 @@ impl Operator for Gt { } impl Operator for Lt { + fn id(&self) -> i32 { + 12 + } + fn precedence(&self) -> i32 { 80 } @@ -467,6 +525,10 @@ impl Operator for Lt { } impl Operator for Geq { + fn id(&self) -> i32 { + 13 + } + fn precedence(&self) -> i32 { 80 } @@ -503,6 +565,10 @@ impl Operator for Geq { } impl Operator for Leq { + fn id(&self) -> i32 { + 14 + } + fn precedence(&self) -> i32 { 80 } @@ -539,6 +605,10 @@ impl Operator for Leq { } impl Operator for And { + fn id(&self) -> i32 { + 15 + } + fn precedence(&self) -> i32 { 75 } @@ -561,6 +631,10 @@ impl Operator for And { } impl Operator for Or { + fn id(&self) -> i32 { + 16 + } + fn precedence(&self) -> i32 { 70 } @@ -583,6 +657,10 @@ impl Operator for Or { } impl Operator for Not { + fn id(&self) -> i32 { + 17 + } + fn precedence(&self) -> i32 { 110 } @@ -604,17 +682,26 @@ impl Operator for Not { } impl Operator for Tuple { + fn id(&self) -> i32 { + 18 + } + fn precedence(&self) -> i32 { 40 } fn max_argument_amount(&self) -> Option { - Some(2) + None } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - if let Value::Tuple(tuple) = &arguments[0] { + if arguments.len() < 2 { + return Err(EvalexprError::wrong_operator_argument_amount(arguments.len(), 2)); + } + + Ok(Value::Tuple(arguments.iter().cloned().collect())) + + /*if let Value::Tuple(tuple) = &arguments[0] { let mut tuple = tuple.clone(); if let Value::Tuple(tuple2) = &arguments[1] { tuple.extend(tuple2.iter().cloned()); @@ -633,11 +720,15 @@ impl Operator for Tuple { arguments[1].clone(), ])) } - } + }*/ } } impl Operator for Assign { + fn id(&self) -> i32 { + 19 + } + fn precedence(&self) -> i32 { 50 } @@ -664,10 +755,18 @@ impl Operator for Assign { } impl Operator for Chain { + fn id(&self) -> i32 { + 20 + } + fn precedence(&self) -> i32 { 0 } + fn is_flatten_chains(&self) -> bool { + true + } + fn max_argument_amount(&self) -> Option { Some(2) } @@ -682,6 +781,10 @@ impl Operator for Chain { } impl Operator for Const { + fn id(&self) -> i32 { + 21 + } + fn precedence(&self) -> i32 { 200 } @@ -698,6 +801,10 @@ impl Operator for Const { } impl Operator for VariableIdentifier { + fn id(&self) -> i32 { + 22 + } + fn precedence(&self) -> i32 { 200 } @@ -722,6 +829,10 @@ impl Operator for VariableIdentifier { } impl Operator for FunctionIdentifier { + fn id(&self) -> i32 { + 23 + } + fn precedence(&self) -> i32 { 190 } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index c6d2956..6aff4ed 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -337,6 +337,9 @@ impl Node { .last_mut() .unwrap() .insert_back_prioritized(node, false) + } else if self.children.last().unwrap().operator().id() == node.operator().id() && node.operator().is_flatten_chains() && !self.children.last().unwrap().has_enough_children() { + // The operators will be chained together, and the next value will be added to this nodes last child. + Ok(()) } else { if node.operator().is_leaf() { return Err(EvalexprError::AppendedToLeafNode); diff --git a/src/value/mod.rs b/src/value/mod.rs index b2e8cee..17aafe2 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -194,6 +194,10 @@ impl From for EvalexprResult { } } +impl From<()> for Value { + fn from(_: ()) -> Self { Value::Empty } +} + #[cfg(test)] mod tests { use value::{TupleType, Value}; diff --git a/tests/integration.rs b/tests/integration.rs index 2c90c9f..5fbd5a2 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -614,3 +614,17 @@ fn test_serde() { assert_eq!(manual_tree.eval(), serde_tree.eval()); } } + +#[test] +fn test_tuple_definitions() { + assert_eq!(eval_empty("()"), Ok(())); + assert_eq!(eval_int("(3)"), Ok(3)); + assert_eq!(eval_tuple("(3, 4)"), Ok(vec![Value::from(3), Value::from(4)])); + assert_eq!(eval_tuple("2, (5, 6)"), Ok(vec![Value::from(2), Value::from(vec![Value::from(5), Value::from(6)])])); + assert_eq!(eval_tuple("1, 2"), Ok(vec![Value::from(1), Value::from(2)])); + assert_eq!(eval_tuple("1, 2, 3, 4"), Ok(vec![Value::from(1), Value::from(2), Value::from(3), Value::from(4)])); + assert_eq!(eval_tuple("(1, 2, 3), 5, 6, (true, false, 0)"), Ok(vec![Value::from(vec![Value::from(1), Value::from(2), Value::from(3)]), Value::from(5), Value::from(6), Value::from(vec![Value::from(true), Value::from(false), Value::from(0)])])); + assert_eq!(eval_tuple("1, (2)"), Ok(vec![Value::from(1), Value::from(2)])); + assert_eq!(eval_tuple("1, ()"), Ok(vec![Value::from(1), Value::from(())])); + assert_eq!(eval_tuple("1, ((2))"), Ok(vec![Value::from(1), Value::from(2)])); +}