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
- `+` as a unary operator
- Compare operators => *, / should have the same priority!
- Commands
- Documentation (usage)
- Documentation (comments)

View File

@ -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 {

View File

@ -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<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(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);
}
}