Skip to content

Commit

Permalink
date parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
dzhibas committed Feb 11, 2024
1 parent e2160be commit 319b823
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 20 deletions.
155 changes: 155 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ crate-type = ["cdylib", "rlib"]
opt-level = "z"

[dependencies]
chrono = "0.4.34"
nom = "7.1.3"
wasm-bindgen = "0.2"

Expand Down
3 changes: 2 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- [ ] Atom parsing for Date & DateTime
- [+] Atom parsing for Date
- [+] Date converted to chrono datetime for comparison later
- [ ] Scopes and negated scopes
- [ ] either lower() or upper() function calls or case insensitive string comparison operators
- [+] support for single quote strings
Expand Down
6 changes: 6 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use core::fmt;

use chrono::NaiveDate;

/// TODO: add date and datetime as its common
#[derive(Debug, Clone, PartialEq)]
pub enum Atom {
Expand All @@ -8,6 +10,8 @@ pub enum Atom {
Float(f64),
Boolean(bool),
Variable(String),
Date(NaiveDate),
DateTime(String),
}

impl fmt::Display for Atom {
Expand All @@ -18,6 +22,8 @@ impl fmt::Display for Atom {
Atom::Float(float) => write!(f, "{float}"),
Atom::Boolean(bool) => write!(f, "{bool}"),
Atom::Variable(var) => write!(f, "{var}"),
Atom::Date(var) => write!(f, "{var}"),
Atom::DateTime(var) => write!(f, "{var}"),
}
}
}
Expand Down
58 changes: 39 additions & 19 deletions src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use chrono::NaiveDate;
use nom::{
branch::alt,
bytes::complete::{tag, tag_no_case, take_until},
character::complete::{alpha1, alphanumeric1, char, digit1, multispace0},
combinator::{cut, map, opt, recognize},
bytes::complete::{tag, tag_no_case, take_until, take_while_m_n},
character::{
complete::{alpha1, alphanumeric1, char, digit1, multispace0},
is_digit,
},
combinator::{cut, map, map_res, opt, recognize},
error::ParseError,
multi::{many0, many0_count, separated_list0},
multi::{many0, many0_count, many_m_n, separated_list0},
number::complete::double,
sequence::{delimited, pair, preceded, tuple},
IResult,
Expand Down Expand Up @@ -53,6 +57,15 @@ fn parse_boolean(i: &str) -> IResult<&str, Atom> {
map(parser, Atom::Boolean)(i)
}

fn parse_date(i: &str) -> IResult<&str, Atom> {
let parser = recognize(tuple((digit1, char('-'), digit1, char('-'), digit1)));

map(parser, |date_str: &str| {
let dt = NaiveDate::parse_from_str(date_str, "%Y-%m-%d").expect("Invalid date format");
Atom::Date(dt)
})(i)
}

fn parse_string(i: &str) -> IResult<&str, Atom> {
let parser_a = delimited(tag("\""), take_until("\""), tag("\""));
let parser_b = delimited(tag("\'"), take_until("\'"), tag("\'"));
Expand All @@ -70,6 +83,7 @@ fn parse_variable(i: &str) -> IResult<&str, Atom> {

fn parse_atom(i: &str) -> IResult<&str, Atom> {
alt((
parse_date,
parse_string,
parse_boolean,
parse_float,
Expand Down Expand Up @@ -274,6 +288,17 @@ mod tests {
assert_eq!(res.is_err(), true);
}

#[test]
fn test_parse_date() {
let a = "2004-12-23";
let res = parse_date(a);
assert_eq!(res.is_ok(), true);
if let Ok((i, v)) = res {
assert_eq!(i, "");
assert_eq!(v, Atom::Date(NaiveDate::from_ymd_opt(2004,12,23).unwrap()));
}
}

#[test]
fn test_single_quote_string() {
let a = "a='demo demo'";
Expand All @@ -284,19 +309,14 @@ mod tests {
}
}

// #[test]
// fn test_extreme_test() {
// /// TODO:
// /// scopes with negates (!(a=b) and c=d)
// /// date/date time Atom
// /// function calls to lower / upper
// /// values > variables should be strings
// let expression = r###"a = b and c=d and something not in (1,2,3) or lower(z) == "demo car" or
// z == "demo car" or
// g in (4,5,6) and z == "demo car" or
// model in (ms,mx,m3,my) and created >= 2024-01-01
// and demo == false"###;
// let (i, v) = parse(expression).unwrap();
// assert_eq!(i, "");
// }
// #[test]
// fn test_extreme_test() {
// let expression = r###"a = b and c=d and something not in (1,2,3) or lower(z) == "demo car" or
// z == "demo car" or
// g in (4,5,6) and z == "demo car" or
// model in (ms,mx,m3,my) and created >= 2024-01-01
// and demo == false"###;
// let (i, v) = parse(expression).unwrap();
// assert_eq!(i, "");
// }
}

0 comments on commit 319b823

Please sign in to comment.