From d4a24eef7fd410c147de201d776089e0601317d5 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 12 Jun 2020 00:48:18 +0200 Subject: 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. --- src/fexpr/grammar.lalrpop | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'src/fexpr/grammar.lalrpop') 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 = { "any" "(" "player" ":" ")" => filters::player::any(<>), "exists" "(" "player" ":" ")" => filters::player::any(<>), + >, + >, + "(" ")", } @@ -175,6 +181,22 @@ Date: DateTime = { .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: Box = { + => filters::values::comparison(lhs, op, rhs), +} + Comma: HashSet = { ",")*> => { let mut result = v.into_iter().collect::>(); @@ -183,6 +205,16 @@ Comma: HashSet = { }, } +DateProducer: Box = { + => filters::values::constant(<>), + "-time" => filters::values::time(), +} + +DurationProducer: Box = { + => 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, _ -- cgit v1.2.3