Skip to content

Commit

Permalink
in array and variable==string comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
dzhibas committed Feb 16, 2024
1 parent 489226e commit b17b0aa
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bool_expr_parser_nom"
version = "0.2.4"
version = "0.2.5"
edition = "2021"
authors = ["Nikolajus Krauklis <[email protected]>"]

Expand Down
20 changes: 18 additions & 2 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use core::fmt;

use chrono::NaiveDate;

/// TODO: add date and datetime as its common
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub enum Atom {
String(String),
Number(i32),
Expand All @@ -14,6 +13,23 @@ pub enum Atom {
DateTime(String),
}

impl PartialEq<Atom> for Atom {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Atom::String(s1), Atom::String(s2)) => s1 == s2,
(Atom::Variable(v1), Atom::Variable(v2)) => v1 == v2,
(Atom::String(v1), Atom::Variable(v2)) => v1 == v2,
(Atom::Variable(v1), Atom::String(v2)) => v1 == v2,
(Atom::Number(n1), Atom::Number(n2)) => n1 == n2,
(Atom::Float(f1), Atom::Float(f2)) => f1 == f2,
(Atom::Boolean(b1), Atom::Boolean(b2)) => b1 == b2,
(Atom::Date(d1), Atom::Date(d2)) => d1 == d2,
(Atom::DateTime(t1), Atom::DateTime(t2)) => t1 == t2,
_ => false,
}
}
}

impl PartialOrd for Atom {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self {
Expand Down
81 changes: 78 additions & 3 deletions src/eval.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::collections::HashMap;

use crate::ast::{AstNode, Atom, ComparisonOp};
use crate::ast::{ArrayOp, AstNode, Atom, ComparisonOp};

pub fn eval<'a>(expr: &AstNode, context: &HashMap<&str, Atom>) -> Result<bool, &'a str> {
let mut result = false;
result = match expr {
// true || false
AstNode::Constant(var) => {
let mut result = false;
if let Atom::Boolean(v) = var {
Expand All @@ -18,9 +19,9 @@ pub fn eval<'a>(expr: &AstNode, context: &HashMap<&str, Atom>) -> Result<bool, &
}
result
}
// a == 3
// a < 3
AstNode::Compare(var, op, val) => {
// check var in context
// compare with val
let context_val = context.get(var.as_str().unwrap());
let val_content = match val.as_ref() {
AstNode::Constant(a) => Some(a),
Expand All @@ -41,6 +42,39 @@ pub fn eval<'a>(expr: &AstNode, context: &HashMap<&str, Atom>) -> Result<bool, &
false
}
}
// x in (1, 2, 3)
AstNode::Array(var, op, list) => {
let mut result = false;
if let AstNode::List(vec_list) = list.as_ref() {
if let AstNode::Variable(Atom::Variable(var)) = var.as_ref() {
let var_value = context.get(&var.as_str());
if let Some(search_value) = var_value {
match op {
ArrayOp::In => {
// check if this value is in the list
for i in vec_list.iter() {
if search_value == i {
result = true;
break;
}
}
}
ArrayOp::NotIn => {
// a not in (c,d)
let mut found = false;
for i in vec_list.iter() {
if search_value == i {
found = true;
}
}
result = !found;
}
}
}
}
}
result
}
_ => false,
};
Ok(result)
Expand All @@ -51,6 +85,47 @@ mod tests {

use super::*;

#[test]
fn array_eval_test() {
let context = HashMap::from([
("x", Atom::Number(10)),
("y", Atom::String("tree".to_string())),
]);
let (i, expr) = parse("y in ('one', 'two', 'tree')").unwrap();
let res = eval(&expr, &context).unwrap();
assert_eq!(res, true);

assert_eq!(
false,
eval(
&expr,
&HashMap::from([("y", Atom::String("four".to_string())),])
)
.unwrap()
);

assert_eq!(
true,
eval(
&parse("y not in ('one','two','tree')").unwrap().1,
&HashMap::from([("y", Atom::String("four".to_string())),])
)
.unwrap()
);
}

#[test]
fn compare_variable_with_string_in_array_test() {
assert_eq!(
true,
eval(
&parse("y in (one,two,tree)").unwrap().1,
&HashMap::from([("y", Atom::String("two".to_string())),])
)
.unwrap()
);
}

#[test]
fn test_comparison_expr_eval() {
let context = HashMap::from([
Expand Down

0 comments on commit b17b0aa

Please sign in to comment.