bug: swap 'and' and 'or' calls around for correct precedence

This commit is contained in:
ClementTsang 2020-05-04 00:27:21 -04:00
parent da7c1db426
commit a56156a8f2
1 changed files with 74 additions and 72 deletions

View File

@ -9,8 +9,9 @@ use crate::{
use std::collections::VecDeque; use std::collections::VecDeque;
const DELIMITER_LIST: [char; 6] = ['=', '>', '<', '(', ')', '\"']; const DELIMITER_LIST: [char; 6] = ['=', '>', '<', '(', ')', '\"'];
const AND_LIST: [&str; 2] = ["and", "&&"];
const OR_LIST: [&str; 2] = ["or", "||"]; const OR_LIST: [&str; 2] = ["or", "||"];
const AND_LIST: [&str; 2] = ["and", "&&"];
/// I only separated this as otherwise, the states.rs file gets huge... and this should /// I only separated this as otherwise, the states.rs file gets huge... and this should
/// belong in another file anyways, IMO. /// belong in another file anyways, IMO.
@ -39,15 +40,15 @@ pub trait ProcessQuery {
impl ProcessQuery for ProcWidgetState { impl ProcessQuery for ProcWidgetState {
fn parse_query(&self) -> Result<Query> { fn parse_query(&self) -> Result<Query> {
fn process_string_to_filter(query: &mut VecDeque<String>) -> Result<Query> { fn process_string_to_filter(query: &mut VecDeque<String>) -> Result<Query> {
let mut lhs: And = process_and(query)?; let mut lhs: Or = process_or(query)?;
while query.front().is_some() { while query.front().is_some() {
let rhs = Some(Box::new(process_or(query)?)); let rhs = Some(Box::new(process_and(query)?));
lhs = And { lhs = Or {
lhs: Or { lhs: And {
lhs: Prefix { lhs: Prefix {
and: Some(Box::from(lhs)), or: Some(Box::from(lhs)),
compare_prefix: None, compare_prefix: None,
regex_prefix: None, regex_prefix: None,
}, },
@ -60,21 +61,21 @@ impl ProcessQuery for ProcWidgetState {
Ok(Query { query: lhs }) Ok(Query { query: lhs })
} }
fn process_and(query: &mut VecDeque<String>) -> Result<And> { fn process_or(query: &mut VecDeque<String>) -> Result<Or> {
let mut lhs = process_or(query)?; let mut lhs = process_and(query)?;
let mut rhs: Option<Box<Or>> = None; let mut rhs: Option<Box<And>> = None;
while let Some(queue_top) = query.front() { while let Some(queue_top) = query.front() {
if AND_LIST.contains(&queue_top.to_lowercase().as_str()) { if OR_LIST.contains(&queue_top.to_lowercase().as_str()) {
query.pop_front(); query.pop_front();
rhs = Some(Box::new(process_or(query)?)); rhs = Some(Box::new(process_and(query)?));
if let Some(queue_next) = query.front() { if let Some(queue_next) = query.front() {
if AND_LIST.contains(&queue_next.to_lowercase().as_str()) { if OR_LIST.contains(&queue_next.to_lowercase().as_str()) {
// Must merge LHS and RHS // Must merge LHS and RHS
lhs = Or { lhs = And {
lhs: Prefix { lhs: Prefix {
and: Some(Box::new(And { lhs, rhs })), or: Some(Box::new(Or { lhs, rhs })),
regex_prefix: None, regex_prefix: None,
compare_prefix: None, compare_prefix: None,
}, },
@ -90,24 +91,24 @@ impl ProcessQuery for ProcWidgetState {
} }
} }
Ok(And { lhs, rhs }) Ok(Or { lhs, rhs })
} }
fn process_or(query: &mut VecDeque<String>) -> Result<Or> { fn process_and(query: &mut VecDeque<String>) -> Result<And> {
let mut lhs = process_prefix(query, false)?; let mut lhs = process_prefix(query, false)?;
let mut rhs: Option<Box<Prefix>> = None; let mut rhs: Option<Box<Prefix>> = None;
while let Some(queue_top) = query.front() { while let Some(queue_top) = query.front() {
if OR_LIST.contains(&queue_top.to_lowercase().as_str()) { if AND_LIST.contains(&queue_top.to_lowercase().as_str()) {
query.pop_front(); query.pop_front();
rhs = Some(Box::new(process_prefix(query, false)?)); rhs = Some(Box::new(process_prefix(query, false)?));
if let Some(queue_next) = query.front() { if let Some(queue_next) = query.front() {
if OR_LIST.contains(&queue_next.to_lowercase().as_str()) { if AND_LIST.contains(&queue_next.to_lowercase().as_str()) {
// Must merge LHS and RHS // Must merge LHS and RHS
lhs = Prefix { lhs = Prefix {
and: Some(Box::new(And { or: Some(Box::new(Or {
lhs: Or { lhs, rhs }, lhs: And { lhs, rhs },
rhs: None, rhs: None,
})), })),
regex_prefix: None, regex_prefix: None,
@ -123,7 +124,7 @@ impl ProcessQuery for ProcWidgetState {
} }
} }
Ok(Or { lhs, rhs }) Ok(And { lhs, rhs })
} }
fn process_prefix(query: &mut VecDeque<String>, inside_quotations: bool) -> Result<Prefix> { fn process_prefix(query: &mut VecDeque<String>, inside_quotations: bool) -> Result<Prefix> {
@ -134,11 +135,11 @@ impl ProcessQuery for ProcWidgetState {
} }
// Get content within bracket; and check if paren is complete // Get content within bracket; and check if paren is complete
let and = process_and(query)?; let or = process_or(query)?;
if let Some(close_paren) = query.pop_front() { if let Some(close_paren) = query.pop_front() {
if close_paren.to_lowercase() == ")" { if close_paren.to_lowercase() == ")" {
return Ok(Prefix { return Ok(Prefix {
and: Some(Box::new(and)), or: Some(Box::new(or)),
regex_prefix: None, regex_prefix: None,
compare_prefix: None, compare_prefix: None,
}); });
@ -172,7 +173,7 @@ impl ProcessQuery for ProcWidgetState {
// the close quote checker, add one to the top of the stack. Ugly fix but whatever. // the close quote checker, add one to the top of the stack. Ugly fix but whatever.
query.push_front("\"".to_string()); query.push_front("\"".to_string());
return Ok(Prefix { return Ok(Prefix {
and: None, or: None,
regex_prefix: Some(( regex_prefix: Some((
PrefixType::Name, PrefixType::Name,
StringQuery::Value(String::default()), StringQuery::Value(String::default()),
@ -192,7 +193,7 @@ impl ProcessQuery for ProcWidgetState {
match &prefix_type { match &prefix_type {
PrefixType::Name if !inside_quotations => { PrefixType::Name if !inside_quotations => {
return Ok(Prefix { return Ok(Prefix {
and: None, or: None,
regex_prefix: Some((prefix_type, StringQuery::Value(content))), regex_prefix: Some((prefix_type, StringQuery::Value(content))),
compare_prefix: None, compare_prefix: None,
}) })
@ -212,7 +213,7 @@ impl ProcessQuery for ProcWidgetState {
} }
return Ok(Prefix { return Ok(Prefix {
and: None, or: None,
regex_prefix: Some(( regex_prefix: Some((
prefix_type, prefix_type,
StringQuery::Value(final_content), StringQuery::Value(final_content),
@ -226,7 +227,7 @@ impl ProcessQuery for ProcWidgetState {
// Check next string if possible // Check next string if possible
if let Some(queue_next) = query.pop_front() { if let Some(queue_next) = query.pop_front() {
return Ok(Prefix { return Ok(Prefix {
and: None, or: None,
regex_prefix: Some(( regex_prefix: Some((
prefix_type, prefix_type,
StringQuery::Value(queue_next), StringQuery::Value(queue_next),
@ -236,7 +237,7 @@ impl ProcessQuery for ProcWidgetState {
} }
} else { } else {
return Ok(Prefix { return Ok(Prefix {
and: None, or: None,
regex_prefix: Some(( regex_prefix: Some((
prefix_type, prefix_type,
StringQuery::Value(content), StringQuery::Value(content),
@ -346,7 +347,7 @@ impl ProcessQuery for ProcWidgetState {
} }
return Ok(Prefix { return Ok(Prefix {
and: None, or: None,
regex_prefix: None, regex_prefix: None,
compare_prefix: Some(( compare_prefix: Some((
prefix_type, prefix_type,
@ -398,7 +399,8 @@ impl ProcessQuery for ProcWidgetState {
#[derive(Debug)] #[derive(Debug)]
pub struct Query { pub struct Query {
pub query: And, /// Remember, AND > OR, but and must come after or then.
pub query: Or,
} }
impl Query { impl Query {
@ -418,46 +420,10 @@ impl Query {
} }
} }
#[derive(Debug)]
pub struct And {
pub lhs: Or,
pub rhs: Option<Box<Or>>,
}
impl And {
pub fn process_regexes(
&mut self, is_searching_whole_word: bool, is_ignoring_case: bool,
is_searching_with_regex: bool,
) -> Result<()> {
self.lhs.process_regexes(
is_searching_whole_word,
is_ignoring_case,
is_searching_with_regex,
)?;
if let Some(rhs) = &mut self.rhs {
rhs.process_regexes(
is_searching_whole_word,
is_ignoring_case,
is_searching_with_regex,
)?;
}
Ok(())
}
pub fn check(&self, process: &ConvertedProcessData) -> bool {
if let Some(rhs) = &self.rhs {
self.lhs.check(process) && rhs.check(process)
} else {
self.lhs.check(process)
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Or { pub struct Or {
pub lhs: Prefix, pub lhs: And,
pub rhs: Option<Box<Prefix>>, pub rhs: Option<Box<And>>,
} }
impl Or { impl Or {
@ -490,6 +456,42 @@ impl Or {
} }
} }
#[derive(Debug)]
pub struct And {
pub lhs: Prefix,
pub rhs: Option<Box<Prefix>>,
}
impl And {
pub fn process_regexes(
&mut self, is_searching_whole_word: bool, is_ignoring_case: bool,
is_searching_with_regex: bool,
) -> Result<()> {
self.lhs.process_regexes(
is_searching_whole_word,
is_ignoring_case,
is_searching_with_regex,
)?;
if let Some(rhs) = &mut self.rhs {
rhs.process_regexes(
is_searching_whole_word,
is_ignoring_case,
is_searching_with_regex,
)?;
}
Ok(())
}
pub fn check(&self, process: &ConvertedProcessData) -> bool {
if let Some(rhs) = &self.rhs {
self.lhs.check(process) && rhs.check(process)
} else {
self.lhs.check(process)
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum PrefixType { pub enum PrefixType {
Pid, Pid,
@ -525,7 +527,7 @@ impl std::str::FromStr for PrefixType {
#[derive(Debug)] #[derive(Debug)]
pub struct Prefix { pub struct Prefix {
pub and: Option<Box<And>>, pub or: Option<Box<Or>>,
pub regex_prefix: Option<(PrefixType, StringQuery)>, pub regex_prefix: Option<(PrefixType, StringQuery)>,
pub compare_prefix: Option<(PrefixType, NumericalQuery)>, pub compare_prefix: Option<(PrefixType, NumericalQuery)>,
} }
@ -535,8 +537,8 @@ impl Prefix {
&mut self, is_searching_whole_word: bool, is_ignoring_case: bool, &mut self, is_searching_whole_word: bool, is_ignoring_case: bool,
is_searching_with_regex: bool, is_searching_with_regex: bool,
) -> Result<()> { ) -> Result<()> {
if let Some(and) = &mut self.and { if let Some(or) = &mut self.or {
return and.process_regexes( return or.process_regexes(
is_searching_whole_word, is_searching_whole_word,
is_ignoring_case, is_ignoring_case,
is_searching_with_regex, is_searching_with_regex,
@ -586,7 +588,7 @@ impl Prefix {
} }
} }
if let Some(and) = &self.and { if let Some(and) = &self.or {
and.check(process) and.check(process)
} else if let Some((prefix_type, query_content)) = &self.regex_prefix { } else if let Some((prefix_type, query_content)) = &self.regex_prefix {
if let StringQuery::Regex(r) = query_content { if let StringQuery::Regex(r) = query_content {