eles 1.0.0

ELES; Extensible Logical Expression Solver
Documentation
use anyhow::{
 anyhow,
 bail,
 Context,
 Result
};
use eles::solve;
use once_cell::sync::Lazy;
use regex::Regex;
use std::collections::HashMap;

enum DatabaseValue
{
 S(String),
 N(f64)
}

type Database = HashMap<String, DatabaseValue>;

static DATABASE: Lazy<Database> = Lazy::<Database>::new(|| {
 let mut db = Database::new();
 db.insert("abc".to_string(), DatabaseValue::S("abc".to_string()));
 db.insert("abc.p".to_string(), DatabaseValue::N(std::f64::consts::PI));
 db.insert("def".to_string(), DatabaseValue::S("def".to_string()));
 db.insert("def.q".to_string(), DatabaseValue::N(std::f64::consts::SQRT_2));
 db
});

fn data_tester(input: &str) -> Result<bool>
{
 const GTLT_PATTERN: &str = r#"^(?P<lhs>.+)(?P<op>[><][=]?)(?P<rhs>.+)$"#;
 static GTLT: Lazy<Regex> = Lazy::<Regex>::new(|| Regex::new(GTLT_PATTERN).unwrap());
 if input.starts_with("is_exists(")
 {
  let key = input["is_exists(".len()..input.len() - 1].trim();
  let r = DATABASE.contains_key(key);
  println!("[debug] is_exists(key) -> {:?}; key={:?}", r, key);
  Ok(r)
 }
 else if let Some(captures) = GTLT.captures(input)
 {
  let lhs = captures.name("lhs").context("lhs error 1")?.as_str().trim();
  let lhs = DATABASE.get(lhs).context("lhs error 2")?;
  let lhs = match lhs
  {
   DatabaseValue::N(lhs) => *lhs,
   _ => bail!("lhs error 3")
  };

  let op = captures
   .name("op")
   .context("op error 1")?
   .as_str()
   .chars()
   .next()
   .context("op error 2")?;

  let rhs = captures.name("rhs");
  let rhs = rhs.with_context(|| format!("rhs error 1; rhs={:?}", rhs))?.as_str().trim();
  let rhs = rhs.parse::<f64>().map_err(|_| anyhow!("rhs error 2; rhs={:?}", rhs))?;

  let r = match op
  {
   '>' =>
   {
    println!("[debug] lhs > rhs -> {:?}; lhs={:?} rhs={:?}", lhs > rhs, lhs, rhs);
    lhs > rhs
   },
   '<' =>
   {
    println!("[debug] lhs < rhs -> {:?}; lhs={:?} rhs={:?}", lhs < rhs, lhs, rhs);
    lhs < rhs
   },
   _ => bail!("opration error 1")
  };
  Ok(r)
 }
 else
 {
  Err(anyhow!("syntax error 1; input={:?}", input))
 }
}

fn main()
{
 let query = "(( is_exists(abc) && abc.p > 3.0 && abc.p < 4.0 )) || (( is_exists(def) && def.q > 1.23e-6 && def.q < 1.66e-6 ))";
 let r = solve(&query, data_tester);
 println!("{:?}", r);
}