From c3686172cda8791c15f3b8d95a73740daa356f13 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 6 Apr 2023 09:35:52 -0700 Subject: [PATCH] Improved operator ordering --- README.md | 1 - src/parser/treeify.rs | 28 ++++++++++++++-------------- src/tokens.rs | 28 +++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index e013853..3f91d1e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ This is nowhere near complete. Stay tuned. ## Before For 1.0 release - `+` as a unary operator - - Compare operators => *, / should have the same priority! - Commands - Documentation (usage) - Documentation (comments) diff --git a/src/parser/treeify.rs b/src/parser/treeify.rs index a4f1b95..29a9636 100644 --- a/src/parser/treeify.rs +++ b/src/parser/treeify.rs @@ -92,31 +92,31 @@ fn treeify_binary( // Precedence of this operator - let this_val = { + let this_op = { let PreToken::PreOperator(l, s) = this else {panic!()}; let o = Operator::from_string(s); if o.is_none() { return Err((*l, ParserError::Syntax)); } - o.unwrap().as_int() + o.unwrap() }; // Precedence of the operators contesting our arguments - let left_val = if i > 1 { + let left_op = if i > 1 { let PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; let o = Operator::from_string(s); if o.is_none() { return Err((*l, ParserError::Syntax)); } - Some(o.unwrap().as_int()) + Some(o.unwrap()) } else { None }; - let right_val = if i < g_inner.len()-2 { + let right_op = if i < g_inner.len()-2 { let PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; let o = Operator::from_string(s); if o.is_none() { return Err((*l, ParserError::Syntax)); } - Some(o.unwrap().as_int()) + Some(o.unwrap()) } else { None }; if { - (left_val.is_none() || this_val >= left_val.unwrap()) && - (right_val.is_none() || this_val >= right_val.unwrap()) + (left_op.is_none() || this_op >= left_op.unwrap()) && + (right_op.is_none() || this_op >= right_op.unwrap()) } { // This operator has higher precedence, it takes both arguments let left_pre = g_inner.remove(i-1).unwrap(); @@ -208,31 +208,31 @@ fn treeify_unary( } else { // Precedence of this operator - let this_val = { + let this_op = { let PreToken::PreOperator(l, s) = this else {panic!()}; let o = Operator::from_string(s); if o.is_none() { return Err((*l, ParserError::Syntax)); } - o.unwrap().as_int() + o.unwrap() }; // Precedence of the operator contesting its argument - let next_val = if left_associative { + let next_op = if left_associative { if i > 1 { let PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; let o = Operator::from_string(s); if o.is_none() { return Err((*l, ParserError::Syntax)); } - Some(o.unwrap().as_int()) + Some(o.unwrap()) } else { None } } else { if i < g_inner.len()-2 { let PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; let o = Operator::from_string(s); if o.is_none() { return Err((*l, ParserError::Syntax)); } - Some(o.unwrap().as_int()) + Some(o.unwrap()) } else { None } }; - if next_val.is_none() || this_val > next_val.unwrap() { + if next_op.is_none() || this_op > next_op.unwrap() { let this_pre = g_inner.remove(i).unwrap(); let next_pre: PreToken; let next: Token; if left_associative { diff --git a/src/tokens.rs b/src/tokens.rs index 8d1c784..5478909 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::cmp::Ordering; use crate::quantity::Quantity; @@ -90,6 +91,27 @@ pub enum Operator { // Not accessible from prompt Flip, } + +impl PartialEq for Operator { + fn eq(&self, other: &Self) -> bool { + self.as_int() == other.as_int() + } +} + +impl PartialOrd for Operator { + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (Operator::Add, Operator::Subtract) + | (Operator::Subtract, Operator::Add) + | (Operator::Multiply, Operator::Divide) + | (Operator::Divide, Operator::Multiply) + => {Some(Ordering::Equal)} + + _ => { self.as_int().partial_cmp(&other.as_int()) } + } + } +} + #[derive(Debug)] #[derive(Copy, Clone)] pub enum Function { @@ -243,7 +265,7 @@ impl Operator { fn add_parens_to_arg(&self, arg: &Token) -> String { let mut astr: String = arg.print(); if let Token::Operator(o,_) = arg { - if o.as_int() < self.as_int() { + if o < self { astr = format!("({})", astr); } } @@ -339,14 +361,14 @@ impl Operator { let mut astr: String = a.print(); if let Token::Operator(o,_) = a { - if o.as_int() < self.as_int() { + if o < self { astr = format!("({})", astr); } } let mut bstr: String = b.print(); if let Token::Operator(o,_) = b { - if o.as_int() < self.as_int() { + if o < self { bstr = format!("({})", astr); } }