Improved operator ordering

pull/2/head
Mark 2023-04-06 09:35:52 -07:00
parent aa90d798c9
commit c3686172cd
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
3 changed files with 39 additions and 18 deletions

View File

@ -9,7 +9,6 @@ This is nowhere near complete. Stay tuned.
## Before For 1.0 release ## Before For 1.0 release
- `+` as a unary operator - `+` as a unary operator
- Compare operators => *, / should have the same priority!
- Commands - Commands
- Documentation (usage) - Documentation (usage)
- Documentation (comments) - Documentation (comments)

View File

@ -92,31 +92,31 @@ fn treeify_binary(
// Precedence of this operator // Precedence of this operator
let this_val = { let this_op = {
let PreToken::PreOperator(l, s) = this else {panic!()}; let PreToken::PreOperator(l, s) = this else {panic!()};
let o = Operator::from_string(s); let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); } if o.is_none() { return Err((*l, ParserError::Syntax)); }
o.unwrap().as_int() o.unwrap()
}; };
// Precedence of the operators contesting our arguments // 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 PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()};
let o = Operator::from_string(s); let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); } if o.is_none() { return Err((*l, ParserError::Syntax)); }
Some(o.unwrap().as_int()) Some(o.unwrap())
} else { None }; } 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 PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()};
let o = Operator::from_string(s); let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); } if o.is_none() { return Err((*l, ParserError::Syntax)); }
Some(o.unwrap().as_int()) Some(o.unwrap())
} else { None }; } else { None };
if { if {
(left_val.is_none() || this_val >= left_val.unwrap()) && (left_op.is_none() || this_op >= left_op.unwrap()) &&
(right_val.is_none() || this_val >= right_val.unwrap()) (right_op.is_none() || this_op >= right_op.unwrap())
} { } {
// This operator has higher precedence, it takes both arguments // This operator has higher precedence, it takes both arguments
let left_pre = g_inner.remove(i-1).unwrap(); let left_pre = g_inner.remove(i-1).unwrap();
@ -208,31 +208,31 @@ fn treeify_unary(
} else { } else {
// Precedence of this operator // Precedence of this operator
let this_val = { let this_op = {
let PreToken::PreOperator(l, s) = this else {panic!()}; let PreToken::PreOperator(l, s) = this else {panic!()};
let o = Operator::from_string(s); let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); } if o.is_none() { return Err((*l, ParserError::Syntax)); }
o.unwrap().as_int() o.unwrap()
}; };
// Precedence of the operator contesting its argument // Precedence of the operator contesting its argument
let next_val = if left_associative { let next_op = if left_associative {
if i > 1 { if i > 1 {
let PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; let PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()};
let o = Operator::from_string(s); let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); } if o.is_none() { return Err((*l, ParserError::Syntax)); }
Some(o.unwrap().as_int()) Some(o.unwrap())
} else { None } } else { None }
} else { } else {
if i < g_inner.len()-2 { if i < g_inner.len()-2 {
let PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; let PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()};
let o = Operator::from_string(s); let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); } if o.is_none() { return Err((*l, ParserError::Syntax)); }
Some(o.unwrap().as_int()) Some(o.unwrap())
} else { None } } 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 this_pre = g_inner.remove(i).unwrap();
let next_pre: PreToken; let next: Token; let next_pre: PreToken; let next: Token;
if left_associative { if left_associative {

View File

@ -1,4 +1,5 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use std::cmp::Ordering;
use crate::quantity::Quantity; use crate::quantity::Quantity;
@ -90,6 +91,27 @@ pub enum Operator {
// Not accessible from prompt // Not accessible from prompt
Flip, 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<Ordering> {
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(Debug)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum Function { pub enum Function {
@ -243,7 +265,7 @@ impl Operator {
fn add_parens_to_arg(&self, arg: &Token) -> String { fn add_parens_to_arg(&self, arg: &Token) -> String {
let mut astr: String = arg.print(); let mut astr: String = arg.print();
if let Token::Operator(o,_) = arg { if let Token::Operator(o,_) = arg {
if o.as_int() < self.as_int() { if o < self {
astr = format!("({})", astr); astr = format!("({})", astr);
} }
} }
@ -339,14 +361,14 @@ impl Operator {
let mut astr: String = a.print(); let mut astr: String = a.print();
if let Token::Operator(o,_) = a { if let Token::Operator(o,_) = a {
if o.as_int() < self.as_int() { if o < self {
astr = format!("({})", astr); astr = format!("({})", astr);
} }
} }
let mut bstr: String = b.print(); let mut bstr: String = b.print();
if let Token::Operator(o,_) = b { if let Token::Operator(o,_) = b {
if o.as_int() < self.as_int() { if o < self {
bstr = format!("({})", astr); bstr = format!("({})", astr);
} }
} }