bug: swap 'and' and 'or' calls around for correct precedence
This commit is contained in:
parent
da7c1db426
commit
a56156a8f2
146
src/app/query.rs
146
src/app/query.rs
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue