diff options
| author | Daniel <kingdread@gmx.de> | 2020-06-12 00:48:18 +0200 | 
|---|---|---|
| committer | Daniel <kingdread@gmx.de> | 2020-06-12 00:48:18 +0200 | 
| commit | d4a24eef7fd410c147de201d776089e0601317d5 (patch) | |
| tree | 8311b261c20d6d5f2d817f63e2cf4a3b213cdd34 /src/fexpr | |
| parent | 1fb3d3259d23410f8bf9879f64de880a11e4f876 (diff) | |
| download | raidgrep-d4a24eef7fd410c147de201d776089e0601317d5.tar.gz raidgrep-d4a24eef7fd410c147de201d776089e0601317d5.tar.bz2 raidgrep-d4a24eef7fd410c147de201d776089e0601317d5.zip | |
initial work on comparison based filters
This enables filters such as
    -time > 2020-01-01
    -time < 2020-02-03
    ...
for time and duration, and later possibly also for more things (such as
a COUNT(...) construct).
This work tries to integrate them into the existing filter system as
seamless as possible, by providing a Comparator which implements
LogFilter.
The "type checking" is done at parse time, so nonsensical comparisons
like -time > 12s flat out give a parse error. This however might be
changed to a more dynamic system with run-time type checking, in which
case we could do away with the type parameter on Producer and simply
work with a generic Value. The comparator would then return an error if
two non-identical types would be compared.
Note that the system does not support arithmetic expressions, only
simple comparisons to constant values.
Diffstat (limited to 'src/fexpr')
| -rw-r--r-- | src/fexpr/grammar.lalrpop | 37 | ||||
| -rw-r--r-- | src/fexpr/mod.rs | 3 | 
2 files changed, 38 insertions, 2 deletions
| diff --git a/src/fexpr/grammar.lalrpop b/src/fexpr/grammar.lalrpop index 45f4fde..c2df097 100644 --- a/src/fexpr/grammar.lalrpop +++ b/src/fexpr/grammar.lalrpop @@ -4,12 +4,15 @@ use super::{      FightOutcome,      filters,      PlayerClass, + +    DateProducer, +    DurationProducer,  };  use evtclib::Boss;  use std::collections::HashSet;  use lalrpop_util::ParseError; -use chrono::{DateTime, Local, TimeZone, Utc, Weekday}; +use chrono::{DateTime, Local, TimeZone, Utc, Weekday, Duration};  use regex::{Regex, RegexBuilder};  grammar; @@ -68,6 +71,9 @@ LogPredicate: Box<dyn filters::log::LogFilter> = {      "any" "(" "player" ":" <PlayerFilter> ")" => filters::player::any(<>),      "exists" "(" "player" ":" <PlayerFilter> ")" => filters::player::any(<>), +    <Comparison<DateProducer>>, +    <Comparison<DurationProducer>>, +      "(" <LogFilter> ")",  } @@ -175,6 +181,22 @@ Date: DateTime<Utc> = {          .map(|d| d.with_timezone(&Utc)),  } +Duration: Duration = { +    duration => Duration::seconds(<>[..<>.len() - 1].parse().unwrap()), +} + +CompOp: filters::values::CompOp = { +    "<" => filters::values::CompOp::Less, +    "<=" => filters::values::CompOp::LessEqual, +    "=" => filters::values::CompOp::Equal, +    ">=" => filters::values::CompOp::GreaterEqual, +    ">" => filters::values::CompOp::Greater, +} + +Comparison<T>: Box<dyn filters::log::LogFilter> = { +    <lhs:T> <op:CompOp> <rhs:T> => filters::values::comparison(lhs, op, rhs), +} +  Comma<T>: HashSet<T> = {      <v:(<T> ",")*> <e:T> => {          let mut result = v.into_iter().collect::<HashSet<_>>(); @@ -183,6 +205,16 @@ Comma<T>: HashSet<T> = {      },  } +DateProducer: Box<dyn DateProducer> = { +    <Date> => filters::values::constant(<>), +    "-time" => filters::values::time(), +} + +DurationProducer: Box<dyn DurationProducer> = { +    <Duration> => filters::values::constant(<>), +    "-duration" => filters::values::duration(), +} +  match {      "player" => "player",      "not" => "not", @@ -194,7 +226,8 @@ match {      r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d" => datetime,      r"\d\d\d\d-\d\d-\d\d" => date, -    r"[\w]+" => word, +    r"\d+s" => duration, +    r"[[:alpha:]][\w]*" => word,      r#""[^"]*""# => string,      _ diff --git a/src/fexpr/mod.rs b/src/fexpr/mod.rs index c6a3a39..1738e44 100644 --- a/src/fexpr/mod.rs +++ b/src/fexpr/mod.rs @@ -11,6 +11,9 @@ use itertools::Itertools;  use lalrpop_util::{lalrpop_mod, lexer::Token, ParseError};  use thiserror::Error; +trait DateProducer = filters::values::Producer<Output = chrono::DateTime<chrono::Utc>>; +trait DurationProducer = filters::values::Producer<Output = chrono::Duration>; +  lalrpop_mod!(#[allow(clippy::all)] pub grammar, "/fexpr/grammar.rs");  #[derive(Debug)] | 
